Naruszenie ochrony pamięci

Witam, odpalając ten program wyskakuje mi naruszenie ochrony pamięci.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
 
typedef struct {
char nazwisko[30], imie[30], oceny[60][4];
int liczba_ocen;
}Student;
 
void normalize(char tekst[30]){
int i;
toupper(tekst[0]);
for(i=1; i<=strlen(tekst); i++)
tolower(tekst[i]);
}
 
int porownaj_studentow(Student a, Student b){
if(strcmp(a.nazwisko, b.nazwisko))
return strcmp(a.imie, b.imie);
else
return strcmp(a.nazwisko, b.nazwisko);
} 
 
int main(){
Student grupa[30];
char im[30],naz[30],oc[4];
int liczba_stud = 0, i;
 
while(!feof(stdin)){
scanf("%s %s %s", im, naz, oc);
normalize(im); normalize (naz);
printf("%s %s \n", im, naz);
 
for(i=0; i<=liczba_stud; i++){
if(!(strcmp(grupa[i].nazwisko,naz)  && (strcmp(grupa[i].imie, im)))){
strcpy(grupa[i].oceny[grupa[i].liczba_ocen],oc);
grupa[i].liczba_ocen++;
}
else {
strcpy(grupa[i].nazwisko,naz);
strcpy(grupa[i].imie,im);
strcpy(grupa[i].oceny[grupa[i].liczba_ocen],oc);
grupa[i].liczba_ocen++;
liczba_stud++;
}
}
}
 
 
}
}

Wygląda na to że to coś z strcpy, jednak argumentów użyłem w dobrej kolejności.

Co powoduje ten błąd?

Masz tu sporo błędów mniejszych i większych.

  1. strlen zwraca uinta. zadeklaruj i jako unsigned int w normalize.

  2. toupper nie ma prawa podmienić w miejscu danych, skoro nie przyjmuje wskaźnika. “tekst[0] = toupper(tekst[0]);” i podobnie w forze.

  3. “for(i=0; i<=liczba_stud; i++)” jest spełnione także po pierwszym wpisie. Jak latasz po niezainicjalizowanym “grupa”, to się nie dziw, że masz AV. (hint: dane są nieokreślone, jeśli sam ich nie wyzerujesz/nie ustawisz)

  4. jak to naprawisz, to uruchom debugger i sprawdź samemu *dlaczego* nie działa.

Gdzie inicjalizujesz IlośćOcen?