私は小さな趣味のプロジェクト( 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
のすべてのキャストを保持する必要があります。
これは間違っているように見えます:
_char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1);
_
おそらく次のようになります。
_char **return_data = malloc ( (MAX_SOURCE_STRINGS+1) * sizeof *return_data );
_
(便宜上スペースが追加されています)。
[〜#〜] edit [〜#〜]:いくつかの追加の説明:_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です。