c - Valgrind 提示 "Invalid write of size 8"

标签 c debugging memory-management valgrind

我正在做一个小型的业余爱好项目 ( 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 );

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

编辑:一些额外的解释: 当您说 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 是(在您的情况下)魔数(Magic Number) 6。

关于c - Valgrind 提示 "Invalid write of size 8",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7668499/

相关文章:

c - 按位运算写入整数的单个字节

debugging - 使用VS Code进行调试不起作用。没有变量,调用堆栈等

c - aligned_alloc 函数要求

ios - UIButton 从内存中释放?

c - MPI_Aint 的大小?

c - 制作共享对象错误时如何修复局部符号'不能使用?

debugging - 戈格兰 : debugging has redundant parameter '--'

c - 释放包含 void * 的结构

c - popen 函数 : Command not found or exited with error status in C program

c++ - Variabel 每次都会给出一个看似随机的答案