C语言 Valgrind 抱怨“大小为 8 的无效写入”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7668499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:50:17  来源:igfitidea点击:

Valgrind complains with "Invalid write of size 8"

cdebuggingmemory-managementvalgrind

提问by AzP

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. 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.

我正在做一个小型的业余项目(www.github.com/AzP/GLSL-Validate),在那里我使用了旧代码(根据我自己的喜好,c 太多,c++ 少,但是,嘿,你能做什么? ) 并且我正在尝试让它在 Linux 和 Windows 上运行。我遇到了几次崩溃(现在希望已修复),但是自从我开始运行 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] = '
==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)
'; 324 fclose(in); 325 if(count==0){ 326 return_data[0]=(char*)malloc(count+2); 327 return_data[0][0]='
char**return_data=(char**)malloc(MAX_SOURCE_STRINGS+1);
'; 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]='
char **return_data = malloc ( (MAX_SOURCE_STRINGS+1) * sizeof *return_data );
'; 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. Does the is 0 bytes inside a block of size 6 alloc'dmean that I can disregard it? I mean '0 bytes' doesn't sound dangerous? But since I posted the question here, I guess you can see that I think that I should pay attention to it.

这是 Valgrind 的输出。是否is 0 bytes inside a block of size 6 alloc'd意味着我可以忽略它?我的意思是“0 字节”听起来不危险?但是既然我把问题贴在这里,我想你可以看到我认为我应该关注它。

##代码##

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.

回答by Omri Barel

This looks wrong:

这看起来不对:

##代码##

Should probably be:

应该是:

##代码##

(spaces added for convenience).

(为方便起见添加了空格)。

EDIT: Some additional explanation: When you say return_data[i]=...you are trying to write something into return_data[i]. Now, return_datais char**, so return_data[i]is char*. So you are writing a pointer into some location in memory.

编辑:一些额外的解释:当你说return_data[i]=...你试图写一些东西到return_data[i]. 现在,return_datachar**return_data[i]也是char*。因此,您正在将指针写入内存中的某个位置。

It looks like your pointers are 8 bytes long (which is fine), but you've only allocated 6 bytes: MAX_SOURCE_STRING+1. So there is a problem.

它看起来像你的指针是8个字节长(这是好的),但你只分配6个字节:MAX_SOURCE_STRING+1。所以有一个问题。

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. So in total you should allocate n * sizeof *return_databytes, where nis (in your case) the magic number 6.

为了解决这个问题,你应该分配足够的空间来保存一个指针数组。每个指针都需要sizeof(char*),也可以写为sizeof(*return_data)sizeof *return_data。因此,您总共应该分配n * sizeof *return_data字节,其中n(在您的情况下)是幻数 6。