我通常喜欢解释良好的问题和答案。但在这种情况下,我真的无法提供更多的线索。
问题是:为什么malloc((给我SIGSEGV?调试波纹管显示程序没有时间测试返回的指向 NULL 的指针并退出。该程序退出了INSIDE MALLOC!
我假设我在 glibc 中的 malloc 很好。我有一个 debian/linux wheezy 系统,更新了,在一个旧的奔腾(i386/i486 arch(。
为了能够跟踪,我生成了一个核心转储。让我们遵循它:
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 bytes
.如果我之前测试过,至少我会对错误进行一些确认。
任何想法,请分享。谢谢。
malloc
(或free
(内部的任何崩溃几乎肯定是堆损坏的迹象,它可以有多种形式:
- 堆缓冲区溢出或下溢
- 释放两次内容
- 释放非堆指针
- 写入释放的块
- 等。
如果没有工具支持,这些错误很难捕获,因为崩溃通常伴随着数千条指令,并且可能多次调用malloc
或稍后free
,这些代码通常位于程序的完全不同的部分,并且离错误的位置很远。
好消息是,像Valgrind或AddressSanitizer这样的工具通常会直接指出问题所在。