Вальгринд жалуется на «Неверная запись размера 8» - PullRequest
9 голосов
/ 06 октября 2011

Я работаю над небольшим хобби-проектом ( www.github.com / AzP / GLSL-Validate ), где я взял старый код (слишком много c и мало c ++ на мой вкус , но эй, что вы можете сделать?) и я пытаюсь запустить его на Linux и Windows. У меня было несколько сбоев (теперь, надеюсь, исправленных), но с тех пор, как я начал запускать Valgrind, чтобы найти проблемы, я застрял с желанием исправить полученные жалобы.

Я просто не вижу, что не так с этим кодом (за исключением того, что его довольно сложно читать с красивыми "волшебными числами", разбросанными по всему месту) в отношении жалоб Valgrind.

Я запускаю Valgrind с помощью следующей команды 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 }

И вот идет вывод Valgrind. Означает ли is 0 bytes inside a block of size 6 alloc'd, что я могу игнорировать это? Я имею в виду «0 байтов» не звучит опасно? Но так как я разместил вопрос здесь, я думаю, вы видите, что я думаю, что я должен обратить на него внимание.

==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)

РЕДАКТИРОВАТЬ: мне нужен код для компиляции в компиляторе C ++, поэтому я должен сохранить все приведения malloc.

1 Ответ

15 голосов
/ 06 октября 2011

Это выглядит неправильно:

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

Вероятно, должно быть:

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

(пробелы добавлены для удобства).

РЕДАКТИРОВАТЬ :Некоторое дополнительное объяснение: когда вы говорите return_data[i]=..., вы пытаетесь что-то записать в return_data[i].Теперь return_data равно char**, поэтому return_data[i] равно char*.Итак, вы пишете указатель в какое-то место в памяти.

Похоже, ваши указатели имеют длину 8 байт (что нормально), но вы выделили только 6 байт: MAX_SOURCE_STRING+1.Таким образом, есть проблема.

Тот факт, что вы пытаетесь записать его в смещение 0, не имеет значения - вы все еще пытаетесь записать больше данных, чем может занять буфер, и вот что такое valgrindжаловаться на.

Чтобы решить эту проблему, вы должны выделить достаточно места для хранения массива указателей.Каждый указатель занимает sizeof(char*), что также может быть записано как sizeof(*return_data) или sizeof *return_data.Таким образом, в общей сложности вы должны выделить n * sizeof *return_data байтов, где n является (в вашем случае) магическим числом 6.

...