2011-10-05 50 views
8

我的工作,我已經採取了舊代碼(太多c和以小C++爲我自己的口味愛好的小項目(www.github.com/AzP/GLSL-Validate),但是,嘿,什麼都可以你呢?),我試圖在Linux和Windows上運行它。我遇到了一些崩潰(現在有希望修復),但是自從我開始運行Valgrind來查找問題時,我陷入了想要解決我得到的抱怨的困境。Valgrind的抱怨與「大小8的無效寫」

我看不出有什麼不對的代碼與問候到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所有的轉換。

+0

也許跟蹤'我'的值,看看他們是否超過5。 –

+0

你的意思是6,如在MAX_SOURCE_STRINGS + 1? – AzP

回答

13

這看起來錯:

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_datachar**,所以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.

+0

感謝您的回答!我將它解釋爲return_data是一個char *數組,它也可以被認爲是一個char數組數組。我想到malloc會分配一個由6個char數組組成的數組。然後代碼在第335行執行另一個malloc,在那裏分配位置爲i的子數組(return_data [i])。所以我們可以通過例如return_data [i] [0]等來達到這個數組。 – AzP

+0

但正如你所說,將MALLOC_SOURCE_STRINGS改爲8實際上是擺脫了投訴。我必須重新思考這個問題,直到我明白我做錯了什麼,如果它符合你的信息=) – AzP

+0

啊,我想我現在明白了。你對這些指針是正確的,我想我們需要6個指針,而且每個指針佔用1個字節,當然不是這種情況。 – AzP