calloc 调用失败,代码崩溃
Posted
技术标签:
【中文标题】calloc 调用失败,代码崩溃【英文标题】:calloc call fails and code crashes 【发布时间】:2012-05-11 02:02:00 【问题描述】:我有一段 C 代码如下,它在下面的 calloc() 调用中崩溃:
... some code
free (ipl->fldptr);
ipl->fldptr = calloc (flds*4, sizeof(struct fldptr_type));
...some more code
我尝试 gdb 并在崩溃时得到以下回溯:
Program received signal SIGSEGV, Segmentation fault.
0x0000003ade478f94 in _int_malloc () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6.x86_64 libgcc-4.4.4-13.el6.x86_64 libstdc++-4.4.4-13.el6.x86_64
(gdb) bt
#0 0x0000003ade478f94 in _int_malloc () from /lib/libc.so.6
#1 0x0000003ade4796d8 in calloc () from /lib/libc.so.6
#2 0x0000000000daf00d in myfunction (ipl=0x106f75f0, flds=11)
at myfile.c:1286
作为调试的一部分,我在 gdb 提示符下执行以下操作:
第 2 帧转到该用户代码堆栈帧 并打印变量的值(flds,指针(ipl),它们看起来没问题。显然没有 NULL 取消引用。
但是 calloc() 仍然失败并且它在那里崩溃。这段代码之前成功执行了多次,但是当应用程序运行一段时间后它会崩溃。 (Mem leak ?? tryint to get valgrind run on it,但碰巧在valgrind memcheck工具下运行时,我的代码崩溃的行为是不可重复的)
我正在寻找一些指针来帮助我调试和修复这个问题。
一些相关信息 - gcc: 4.4.4 。红帽企业 Linux 服务器 6.0 64 位 Linux
【问题讨论】:
很可能您已经损坏了堆并破坏了 *alloc() 内部数据结构。查找此类错误的更简单方法是通过valgrind
运行您的程序。
【参考方案1】:
你可能有一个损坏的堆,例如一些内存太早了free
-d(并且仍然被重用),或者一些缓冲区溢出(或者像ptr[-3]
这样的无效访问)
您应该使用valgrind 来调试此类问题。
你也可以使用Boehm's conservative garbage collector。
您还可以使用gdb
手动查找此类错误。使用watch
gdb 命令并禁用address space layout randomization 应该会有所帮助。
我还建议始终清除您拥有free
-d 的指针,因此在您的代码中将free(x)
替换为free(x), x=NULL
(因此,如果x
被错误地取消引用,您将获得@987654334 @立即)。
您还可以使用具有堆栈保护器功能的更新版本的 GCC(当前版本为 4.7)。见this question。
【讨论】:
我不会在任何地方推荐 Boehm gc,更不用说 C 的初学者了。这是“越差越好”的典型例子,肯定会导致可怕的代码充满内存泄漏和 UB。跨度> 而且它仍然是不正确的,并且经常受到攻击者控制的内存泄漏和内存耗尽的影响。这就是 conservative GC 的意思。见***.com/questions/4039274/… 我不明白为什么使用保守的 GC 是不正确的。例如,scm
和guile
Scheme 实现都使用这样的 GC。为什么GC使用不正确?我认为大多数内存管理方案(例如在 GTK 内部,或在 Qt 或 Apache 或 LibreOffice 内部或在内核内部,或在 GCC 编译器内部)都可以称为“垃圾收集器”...... Boehm 的 GC 有优点也有缺点。我知道他们。
据我所知,GTK/glib 使用了一个引用计数系统,它与 GC 差不多。我怀疑 Qt 也会这样做,因为它是 C++(大多数好的 C++ 代码使用 RAII,它在抽象上等同于引用计数)。至于方案,在垃圾收集嵌入式语言的对象(很容易正确地完成)和垃圾收集宿主语言的对象(这对于 C,设计上是不可能的)有很大的不同。
引用计数是 GC 的一种形式。 (最弱的之一,因为不处理循环引用)。 C 中的 GC 通常是不可能的,但可以通过适当的约定(例如在内核内部,或在 GCC 或 MELT 内部,或使用 Qish GC)或使用提供近似值的库(如保守 GC)。是的,我同意 C 是一种管理内存的糟糕语言。以上是关于calloc 调用失败,代码崩溃的主要内容,如果未能解决你的问题,请参考以下文章