GDB回溯消息"?()中的0x0000000000000000"是什么意思?

时间:2020-03-06 14:36:08  来源:igfitidea点击:

它给出以下输出的回溯是什么意思?

#0  0x00000008009c991c in pthread_testcancel () from /lib/libpthread.so.2
#1  0x00000008009b8120 in sigaction () from /lib/libpthread.so.2
#2  0x00000008009c211a in pthread_mutexattr_init () from /lib/libpthread.so.2
#3  0x0000000000000000 in ?? ()

程序已崩溃,并显示标准信号11,分段错误。
我的应用程序是在FreeBSD 6.3上运行的多线程FastCGI C ++程序,使用pthread作为线程库。

根据信息来源,它已经使用-g进行了编译,并且已加载了我的源代码的所有符号表。

很明显,我的实际代码都没有出现在跟踪中,而是错误似乎源自标准pthread库。特别是什么?? ()????

编辑:最终在我的主代码中将崩溃跟踪到了对标准无效内存的访问。没有解释为什么堆栈跟踪被损坏,但这是另一天的问题:)

解决方案

确保使用调试符号进行编译。 (对于gcc,我认为这是-g选项)。然后,我们应该能够从GDB中获得更多有趣的信息。编译生产版本时,请不要忘记将其关闭。

gdb无法从pthread_mutexattr_init中提取正确的返回地址;它的地址为0。" ??"是在符号表中查找地址0的结果。它找不到符号名称,因此会打印默认的" ??"

不幸的是,我不知道为什么它不能提取正确的寄信人地址。

也许导致崩溃的bug破坏了堆栈(堆栈的覆盖部分)?在这种情况下,回溯可能是无用的。不知道在那种情况下该怎么办...

我们所做的某些操作导致线程库崩溃。由于线程库本身未使用调试符号(-g)进行编译,因此它无法显示发生崩溃的源代码文件或者行号。此外,由于它是线程,因此调用堆栈不会指向文件。不幸的是,这将是一个很难跟踪的错误,我们将需要单步执行代码并尝试在崩溃发生时缩小范围。

我可能会丢失一些东西,但这不是表示有人在使用NULL作为函数指针吗?

#include <stdio.h>

typedef int (*funcptr)(void);

int
func_caller(funcptr f)
{
    return (*f)();
}

int
main()
{
    return func_caller(NULL);
}

如果在gdb中运行回溯,则会产生相同的样式:

rivendell$ gcc -g -O0 foo.c -o foo
rivendell$ gdb --quiet foo
Reading symbols for shared libraries .. done
(gdb) r
Starting program: ...
Reading symbols for shared libraries . done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x00000000 in ?? ()
(gdb) bt
#0    0x00000000 in ?? ()
#1    0x00001f9d in func_caller (f=0) at foo.c:8
#2    0x00001fb1 in main () at foo.c:14

但是,这是一个非常奇怪的崩溃...pthread_mutexattr_init除了分配数据结构和memset之外几乎不做任何其他事情。我会寻找其他事情。是否存在线程库不匹配或者其他问题。我对BSD的了解还有些过时,但是过去一直存在一些问题。