我的程序在正常运行时因分段错误而崩溃。所以我用 GDB 运行它,但是当我这样做时它不会崩溃。为什么会出现这种情况?
我知道 Valgrind 的 FAQ 提到了这一点(在 Valgrind 下不会崩溃),但我在 Google 中找不到任何与 GDB 相关的内容。
我以前也遇到过这种情况(你并不孤单),但我不记得我做了什么来解决问题(我认为这是双重免费)。
我的建议是设置环境来创建核心转储,然后在程序崩溃后使用 GDB 来调查核心转储。在 Bash 中,这是通过
ulimit -c size
完成的,其中 size 可以是任何值;我个人使用 50000 来表示最大大小为 25 MB;单位以 512 字节为增量。
您可以使用 GDB 通过使用
gdb program core
来调查核心转储。
尝试附加到
gdb
内正在运行的进程,继续,然后重现崩溃。换句话说,不要在gdb
内启动程序;相反,正常启动程序,然后attach <pid>
。
有时,当单独单步执行各行时,导致程序崩溃的竞争条件不会显现出来,因为步骤之间的“长时间”暂停已经消除了竞争危险,或者使竞争变得极不可能。
我追踪到了 pthread_detach 调用。我正在做 pthread_detach(&thethread)。我只是拿走了引用并将其更改为 pthread_detach(thethread) 并且工作正常。我不确定,但也许通过分离引用然后在超出范围时再次销毁它来实现双重释放?
如果错误取决于时间,GDB 可以防止它重复出现。
我也遇到过这种情况。
我的解决方案:清理并重建一切。
并不是说这总是能解决所有问题(在OP情况下,问题是一些“真的”错误),但是如果你在遇到如此奇怪的“元”错误时首先这样做,你可以节省一些麻烦和时间。至少根据我的经验,这些东西往往来自于应该重建但没有重建的旧目标文件。在 MinGW 和常规 GCC 中。
GDB
这是我原来的数据结构:
typedef struct linked_list {
node *head;
node *tail;
} list;
typedef struct list_node {
char *string;
struct list_node *next;
} node;
当我创建
list
的新“实例”并指定其
head
和 tail
时,程序在 DGB
之外崩溃了:list *createList(void) {
list *newList = (list *) malloc(sizeof(list));
if (newList == NULL) return;
return newList;
}
在我将
createList
功能更改为以下内容后,一切开始正常工作:
list *createList(void) {
list *newList = (list *) malloc(sizeof(list));
if (newList == NULL) return;
newList->head = (node *) 0;
newList->tail = (node *) 0;
return newList;
}
希望它对遇到与我的未初始化指针示例类似的情况的人有所帮助。
为了回答你为什么会发生这种情况的问题,我认为这是计时问题,因为gdb会收集一些与线程执行相关的数据,这可能会减慢进程的执行速度。如果线程执行缓慢,则问题不会重现。