简体   繁体   English

Valgrind抱怨“写入8号无效”

[英]Valgrind complains with “Invalid write of size 8”

I'm working on a small hobby project ( www.github.com/AzP/GLSL-Validate ) where I've taken old code (too much c and to little c++ for my own taste, but hey, what can you do?) and I'm trying to get it up and running on Linux and Windows. 我正在开发一个小型的爱好项目( www.github.com/AzP/GLSL-Validate ),我已经采用旧代码(过多的c和小c ++用于我自己的口味,但是,嘿,你能做什么? )我正试图在Linux和Windows上运行它。 I've had a couple of crashes (fixed now hopefully), but since I started running Valgrind to find the issues, I got stuck with wanting to fix the complaints I get. 我有几次崩溃(现在有希望修复),但是自从我开始运行Valgrind以找到问题后,我一直想要解决我得到的抱怨。

I just can't see what's wrong with this code (except that it's quite hard to read with nice "magic numbers" spread over the place) with regards to the Valgrind complaints. 我只是看不出这个代码有什么问题(除了在Valgrind投诉方面很难看到很好的“魔术数字”)。

I'm running Valgrind with the following command valgrind --track-origins=yes ./Program 我正在使用以下命令运行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 }

And here comes the Valgrind output. 这是Valgrind的输出。 Does the is 0 bytes inside a block of size 6 alloc'd mean that I can disregard it? is 0 bytes inside a block of size 6 alloc'd是否意味着我可以忽略它? I mean '0 bytes' doesn't sound dangerous? 我的意思是'0字节'听起来不危险? But since I posted the question here, I guess you can see that I think that I should pay attention to it. 但是既然我在这里发布了这个问题,我想你可以看到我认为我应该注意它。

==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: I need the code to compile in a c++ compiler, that's why I have to keep all the casts of malloc . 编辑:我需要在c ++编译器中编译代码,这就是为什么我必须保留malloc所有演员。

This looks wrong: 这看起来不对:

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

Should probably be: 应该是:

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

(spaces added for convenience). (为方便起见,增加了空间)。

EDIT : Some additional explanation: When you say return_data[i]=... you are trying to write something into return_data[i] . 编辑 :一些额外的解释:当你说return_data[i]=...你试图写一些东西到return_data[i] Now, return_data is char** , so return_data[i] is char* . 现在, return_datachar** ,所以return_data[i]char* So you are writing a pointer into some location in memory. 所以你正在将指针写入内存中的某个位置。

It looks like your pointers are 8 bytes long (which is fine), but you've only allocated 6 bytes: MAX_SOURCE_STRING+1 . 看起来您的指针长度为8个字节(很好),但您只分配了6个字节: MAX_SOURCE_STRING+1 So there is a problem. 所以有一个问题。

The fact that you're trying to write it into offset 0 doesn't matter - you're still trying to write more data than the buffer can take, and that's what valgrind is complaining about. 您尝试将其写入偏移0的事实并不重要 - 您仍然在尝试编写比缓冲区更多的数据,这就是valgrind所抱怨的。

To solve the problem, you should allocate enough space to hold an array of pointers. 要解决此问题,您应该分配足够的空间来容纳指针数组。 Each pointer takes sizeof(char*) , which can also be written as sizeof(*return_data) or sizeof *return_data . 每个指针都使用sizeof(char*) ,也可以写为sizeof(*return_data)sizeof *return_data So in total you should allocate n * sizeof *return_data bytes, where n is (in your case) the magic number 6. 所以n * sizeof *return_data你应该分配n * sizeof *return_data字节,其中n是(在你的情况下)幻数6。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM