malloc中的信号11 SIGSEGV是什么意思?

3

我通常喜欢简明易懂的问题和答案。但在这种情况下,我真的不能再给出更多线索了。

问题是:为什么malloc()会给我SIGSEGV?下面的调试显示程序没有时间测试返回的指针是否为NULL并退出。程序在MALLOC内部退出!

我假设我的glibc中的malloc很好。我有一个更新的debian / linux wheezy系统,在旧的pentium(i386 / i486架构)上运行。

为了能够跟踪,我生成了一个核心转储。让我们跟踪它:

iguana$gdb xadreco core-20131207-150611.dump

Core was generated by `./xadreco'.
Program terminated with signal 11, Segmentation fault.
#0  0xb767fef5 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) bt
#0  0xb767fef5 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1  0xb76824bc in malloc () from /lib/i386-linux-gnu/libc.so.6
#2  0x080529c3 in enche_pmovi (cabeca=0xbfd40de0, pmovi=0x...) at xadreco.c:4519
#3  0x0804b93a in geramov (tabu=..., nmovi=0xbfd411f8) at xadreco.c:1473
#4  0x0804e7b7 in minimax (atual=..., deep=1, alfa=-105000, bet...) at xadreco.c:2778
#5  0x0804e9fa in minimax (atual=..., deep=0, alfa=-105000, bet...) at xadreco.c:2827
#6  0x0804de62 in compjoga (tabu=0xbfd41924) at xadreco.c:2508
#7  0x080490b5 in main (argc=1, argv=0xbfd41b24) at xadreco.c:604
(gdb) frame 2
#2  0x080529c3 in enche_pmovi (cabeca=0xbfd40de0, pmovi=0x ...) at xadreco.c:4519
4519        movimento *paux = (movimento *) malloc (sizeof (movimento));
(gdb) l
4516 
4517    void enche_pmovi (movimento **cabeca, movimento **pmovi, int c0, int c1, int c2, int c3, int p, int r, int e, int f, int *nmovi)
4518    {
4519        movimento *paux = (movimento *) malloc (sizeof (movimento));
4520        if (paux == NULL)
4521            exit(1);

当然我需要查看帧2,它是与我的代码相关的最后一个堆栈。但是第4519行会导致SIGSEGV!在第4520行测试paux是否为NULL之前没有时间。
这里是“movimento”(缩写):
typedef struct smovimento
{
    int lance[4];  //move in integer notation
    int roque; // etc. ...

    struct smovimento *prox;// pointer to next
} movimento;

这个程序可以加载大量内存。我知道内存已经到达了极限。但是我认为当内存不可用时,malloc会处理得更好。

在执行期间运行$free -h,我可以看到内存下降到1MB!这没关系。旧电脑只有96MB。而操作系统使用了50MB。

我不知道从哪里开始查找。也许在malloc调用之前检查可用内存?但这听起来浪费计算机资源,因为malloc应该会做到这一点。sizeof(movimento)大约为48字节。如果我在调用之前进行测试,至少我会确认这个错误。

如果有任何想法,请分享。谢谢。


1
在那些在 SIGSEGV 函数之前的函数中,你是否有任何大量的堆栈分配?堆栈有一个有限的大小,如果超过了它,程序可能会以这种方式崩溃。 - Atle
1
这种情况可能是由于在malloc内部使用的内存区域中发生了覆盖。这可能是一个off-by-one索引或通过过期指针访问的结果。 - wildplasser
代码位于函数开头。malloc()出现段错误是因为你损坏了它的记账结构(通常是在分配块的开始和/或结束之前或之后)。 - wildplasser
1
堆栈使用量与此崩溃几乎没有任何关系。而且,free 命令与实际内存可用性无关;它的唯一目的是显示缓存利用效率等信息。这个崩溃几乎肯定是由基于堆的缓冲区溢出引起的。 - R.. GitHub STOP HELPING ICE
1
@SouravGhosh你真的认为避免将类型转换为malloc()会帮助解决这个问题吗?在这种情况下,我强烈建议在问题解决之前避免更改这些转换。OP可能有数百个(代码行>= 4521)这样的转换,现在更改它们只会毫无成果。 - chux - Reinstate Monica
显示剩余9条评论
1个回答

4
任何在malloc(或free)内部发生的崩溃几乎肯定是堆破坏的迹象,而堆破坏可以采取许多形式:
  • 溢出或下溢堆缓冲区
  • 两次释放同一对象
  • 释放非堆指针
  • 写入已释放的块
  • 等等。
这些错误很难在没有工具支持的情况下捕获,因为崩溃通常会在许多千个指令之后发生,并且可能会在程序的完全不同的部分和离错误非常遥远的地方调用许多次mallocfree
好消息是,像ValgrindAddressSanitizer这样的工具通常直接指向问题。

非常感谢您的回答。这可能是我能得到的最好的答案。 - DrBeco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接