【问题标题】:making valgrind happy vs avoiding segfault让 valgrind 开心与避免段错误
【发布时间】:2018-07-31 12:51:50
【问题描述】:

我是 C 新手,正在尝试学习 char 数组数组的动态内存分配,但不知道为什么我不能让 valgrind 对 0 错误感到满意,同时又避免了段错误。我的例子是基于这个例子:

How to dynamically allocate memory for char** in C

从那个例子中,我在下面编写了这个测试代码:

#include <stdlib.h>
#include <stdio.h>

int main (int argc, char* argv[]){
        char **myChar;

        int nEl = 5;
        int nChars = 10;

        myChar = (char**)malloc(sizeof(char*));
        for (int it = 0; it < nEl; it++) {
                myChar[it] = (char*)malloc((nChars) * sizeof(char));
        }

        //for (int it = 0; it < nEl; it++) {
        //        free(myChar[it]);
        //}
        //free(myChar);

        return 0;
}

它按原样编译,运行没有问题,退出并返回 0x0,但 valgrind 抱怨:

4 errors in context 1 of 1:
Invalid write of size 8
   at 0x400583: main (in /home/username/Documents/personal/tmp/cprog2/test2)
 Address 0x5204048 is 0 bytes after a block of size 8 alloc'd
   at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x40054D: main (in /home/username/Documents/personal/tmp/cprog2/test2)

ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 0 from 0)

确定 valgrind 期望 malloc 的 **myChar 和 myChar[it] 是 free(),我取消注释注释的位,但程序段错误和 valgrind 说:

4 errors in context 1 of 2:
Invalid read of size 8
   at 0x4005EF: main (in /home/username/Documents/personal/tmp/cprog2/test2)
 Address 0x5204048 is 0 bytes after a block of size 8 alloc'd
   at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x40058D: main (in /home/username/Documents/personal/tmp/cprog2/test2)


4 errors in context 2 of 2:
Invalid write of size 8
   at 0x4005C3: main (in /home/username/Documents/personal/tmp/cprog2/test2)
 Address 0x5204048 is 0 bytes after a block of size 8 alloc'd
   at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x40058D: main (in /home/username/Documents/personal/tmp/cprog2/test2)

ERROR SUMMARY: 8 errors from 2 contexts (suppressed: 0 from 0)

为什么我不能让 valgrind 满意并编译和运行一个工作应用程序?

【问题讨论】:

  • myChar = (char**)malloc(sizeof(char*)); 您分配(空间用于)单个指针,而不是 5 个。
  • 提示:sizeof(char) 保证为1。无需乘以1
  • 使用ptr = malloc(sizeof *ptr * nElmenets); 易于代码审查和维护。
  • 谢谢大家,现在很明显了。

标签: c malloc free


【解决方案1】:

您没有分配足够的内存:

myChar = (char**)malloc(sizeof(char*));

这为单个 char * 分配空间,但您将此内存视为分配了 5 个(即nEl)。

因此,您写入的内存超出了分配内存的末尾。这就是 Valgrind 在说“地址 0x5204048 在分配大小为 8 的块后为 0 字节”时提醒您的内容。这样做会调用未定义的行为,在这种情况下表现为崩溃。

如果您想要nEl 指针的空间,请分配该空间量:

myChar = malloc(sizeof(char*) * nEl);

另外,don't cast the return value of malloc

【讨论】:

  • 感谢您的回答。关于从 malloc 转换返回,我收到错误:如果我不转换返回,则从“void*”到“char*”[-fpermissive] 的转换无效。我必须在你链接的线程中做更多的阅读才能完全理解为什么会这样
  • @brneuro 这可能意味着您正在编译为 C++ 而不是 C。
  • 啊,事实上我正在努力将其中的一些实现到一个类中。
猜你喜欢
  • 1970-01-01
  • 2012-05-25
  • 2011-07-30
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 2021-03-31
相关资源
最近更新 更多