2011-10-05 8 views
8

Pracuję nad małym projektem hobbystycznym (www.github.com/AzP/GLSL-Validate), w którym wziąłem stary kod (za dużo c do małego C++ dla własnego gustu, ale hej, co może robisz?) i staram się go uruchomić na Linuksie i Windowsie. Miałem kilka awarii (naprawiono to teraz z nadzieją), ale odkąd zacząłem prowadzić Valgrind, aby znaleźć problemy, utknąłem z chęcią naprawienia otrzymywanych skarg.Valgrind narzeka z "Nieprawidłowy napis o rozmiarze 8"

Po prostu nie widzę, co jest nie tak z tym kodem (z wyjątkiem tego, że jest to dość trudne do odczytania z ładnymi "magicznymi liczbami" rozmieszczonymi w tym miejscu) w odniesieniu do skarg Valgrind.

biegnę Valgrind pomocą następującego polecenia valgrind --track-origins=yes ./Program

291 // 
292 // Malloc a string of sufficient size and read a string into it. 
293 // 
294 # define MAX_SOURCE_STRINGS 5 
295 char** ReadFileData(char *fileName) 
296 { 
297  FILE *in = fopen(fileName, "r"); 
298  char *fdata; 
299  int count = 0; 
300  char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1); 
301 
302  //return_data[MAX_SOURCE_STRINGS]=NULL; 
303  if (!in) { 
304   printf("Error: unable to open input file: %s\n", fileName); 
305   return 0; 
306  } 
307 
308  // Count size of file by looping through it 
309  while (fgetc(in) != EOF) 
310   count++; 
311 
312  fseek(in, 0, SEEK_SET); 
313 
314 
315  if (!(fdata = (char *)malloc(count+2))) { 
316    printf("Error allocating memory\n"); 
317    return 0; 
318  } 
319  if (fread(fdata, sizeof(char), count, in) != count) { 
320    printf("Error reading input file: %s\n", fileName); 
321    return 0; 
322  } 
323  fdata[count] = '\0'; 
324  fclose(in); 
325  if(count==0){ 
326   return_data[0]=(char*)malloc(count+2); 
327   return_data[0][0]='\0'; 
328   OutputMultipleStrings=0; 
329   return return_data; 
330  } 
331 
332  int len = (int)(ceil)((float)count/(float)OutputMultipleStrings); 
333  int ptr_len=0,i=0; 
334  while(count>0){ 
335   return_data[i]=(char*)malloc(len+2); 
336   memcpy(return_data[i],fdata+ptr_len,len); 
337   return_data[i][len]='\0'; 
338   count-=(len); 
339   ptr_len+=(len); 
340   if(count<len){ 
341    if(count==0){ 
342    OutputMultipleStrings=(i+1); 
343    break; 
344    } 
345   len = count; 
346   } 
347   ++i; 
348  } 
349  return return_data; 
350 } 

I tu pojawia wyjście Valgrind. Czy is 0 bytes inside a block of size 6 alloc'd oznacza, że ​​mogę go zignorować? Mam na myśli, że "0 bajtów" nie brzmi groźnie? Ale odkąd napisałem tutaj pytanie, wydaje mi się, że widzę, że powinienem zwrócić na to uwagę.

==10570== Invalid write of size 8 
==10570== at 0x401602: ReadFileData(char*) (StandAlone.cpp:335) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== 
==10570== Invalid read of size 8 
==10570== at 0x401624: ReadFileData(char*) (StandAlone.cpp:336) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== 
==10570== Invalid read of size 8 
==10570== at 0x40163F: ReadFileData(char*) (StandAlone.cpp:337) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 
==10570== Address 0x5f627a0 is 0 bytes inside a block of size 6 alloc'd 
==10570== at 0x4C2880D: malloc (vg_replace_malloc.c:236) 
==10570== by 0x401475: ReadFileData(char*) (StandAlone.cpp:300) 
==10570== by 0x4013D8: CompileFile(char*, void*, int, TBuiltInResource const*) (StandAlone.cpp:255) 
==10570== by 0x401016: main (StandAlone.cpp:152) 

EDIT: potrzebuję kodu do kompilacji w C++, dlatego muszę zachować wszelkie odlewy malloc.

+0

Być może śledzisz wartości 'i' i czy kiedykolwiek przekroczysz 5. –

+0

Czy masz na myśli 6, jak w MAX_SOURCE_STRINGS + 1? – AzP

Odpowiedz

13

To wygląda źle:

char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1); 

prawdopodobnie powinien być:

char **return_data = malloc ((MAX_SOURCE_STRINGS+1) * sizeof *return_data); 

(dodany obowiązuje dla wygody).

EDIT: Niektóre dodatkowe wyjaśnienie: Kiedy mówisz return_data[i]=... próbujesz napisać coś na return_data[i]. Teraz return_data jest char**, więc return_data[i] jest char*. Więc piszesz wskaźnik w jakiejś lokalizacji w pamięci.

Wygląda na to, że Twoje wskaźniki mają długość 8 bajtów (co jest w porządku), ale przydzielono tylko 6 bajtów: MAX_SOURCE_STRING+1. Więc jest problem.

Fakt, że próbujesz zapisać go w offsecie 0, nie ma znaczenia - wciąż próbujesz zapisać więcej danych niż bufor może zająć, i na to właśnie narzeka Valgrind.

Aby rozwiązać problem, należy przydzielić wystarczającą ilość miejsca na tablicę wskaźników. Każdy wskaźnik przyjmuje wartość sizeof(char*), która może być również zapisana jako sizeof(*return_data) lub sizeof *return_data. Łącznie powinieneś przydzielić n * sizeof *return_data bajtów, gdzie n jest (w twoim przypadku) magiczną liczbą 6.

+0

Dzięki za odpowiedź! Zinterpretowałem to jako return_data jest tablicą char *, która może być również uważana za tablicę znaków char. Doszedłem do wniosku, że malloc przydzieli tablicę 6 tablic char. Następnie kod wykonuje inne malloc w linii 335, gdzie przydziela tablicę podrzędną w pozycji i (return_data [i]). Tak więc możemy osiągnąć tę tablicę, wykonując na przykład return_data [i] [0] itd. – AzP

+0

Ale tak jak powiedziałeś, zmiana MALLOC_SOURCE_STRINGS na 8 faktycznie pozbędzie się skargi.Muszę to przemyśleć, dopóki nie zrozumiem, co robię źle, i jeśli to pasuje do twoich informacji =) – AzP

+0

Ach, myślę, że dostaję to teraz. Masz rację w odniesieniu do wskaźników, doszedłem do wniosku, że potrzebujemy 6 wskazówek i że zajmują one po 1 bajcie, co oczywiście nie ma miejsca. – AzP

Powiązane problemy