如何调试分段故障

How to debug segmentation fault?

本文关键字:分段 故障 调试 何调试      更新时间:2023-10-16

在循环中,当我将每个元素设置为0或entry_count-1时,它就会工作。当我将其设置为entry_count较小时,它就起作用了,并且我手动而不是循环(sorted_order[0]=0;sorted_older[1]=1;…等等)。

请不要告诉我如何修复我的代码。出于非常具体的原因,我不会使用智能指针或矢量。相反,请关注以下问题:什么样的情况会导致这种segfault?非常感谢。

----旧-----

我正在尝试调试在unix机器上不起作用的代码。代码的要点是:

int *sorted_array = (int*)memory;
// I know that this block is large enough
// It is allocated by malloc earlier
for (int i = 0; i < entry_count; ++i){
  sorted_array[i] = i;
}

循环中的某个地方似乎出现了分段故障。不幸的是,切换到调试模式会使segfault停止。使用cout调试,我发现它一定在循环中。

接下来,我想知道segfault在循环中发生了多远,所以我添加了:

std::cout << i << 'n';

它显示了它应该循环的整个范围,并且没有分段故障。

经过更多的实验,我最终在循环之前创建了一个字符串流,并在循环的每次迭代中向其中写入一个空字符串,因此没有segfault。

我尝试了其他各种各样的操作,试图弄清楚发生了什么。我尝试设置一个变量j=I;诸如此类的东西,但我还没有找到任何有效的东西。

运行valgrind时,我得到的关于segfault的唯一信息是,这是一个"一般保护故障",以及对11的默认响应。它还提到,有一个条件跳转或移动取决于未初始化的值,但看看代码,我不知道这是怎么可能的。

这可能是什么?我没有什么可探索的想法了。

这显然是程序中内存使用无效的症状。通过查看代码片段很难找到这一点,因为这很可能是已经发生的其他糟糕事情的副作用。

然而,正如您在问题中提到的,您可以使用Valgrind附加程序,因为它是可复制的。所以你可能想附加你的程序(a.out)。

$valgrind--tool=memcheck--db attach=yes/a.out

这样,当检测到第一个内存错误时,Valgrind会将您的程序附加到调试器中,这样您就可以进行实时调试(GDB)。这应该是理解和解决问题的最佳方式。

一旦你能够找出你的第一个错误,修复它并重新运行它,看看你还有什么其他错误。应执行这些步骤,直到Valgrind没有报告错误为止。

然而,您应该避免在现代C++程序中使用原始指针,并按照其他人的建议开始使用std::vector std::unique_ptr

Valgrind和GDB非常有用。

我以前使用的最新的是GDB——我喜欢它,因为它向我显示了分段故障所在的确切行号

以下是一些可以指导您使用GDB:的资源

GDB教程1

GDB教程2

如果你仍然不知道如何使用GDB与这些教程,谷歌上有很多!只需使用GDB搜索调试分段故障!

祝你好运:)

这很难,我使用valgrind工具来调试seg故障,它通常指向违规。

您的问题可能是正在写入的释放内存,即sorted_array超出范围或被释放。随着数据分配的变化,添加更多的代码会隐藏这个问题。

经过几天的实验,我发现了真正发生的事情

由于某种原因,机器在未对齐的访问上发生故障。也就是说,我正在写的整数并没有被写入到四个字节的倍数的内存边界。在循环之前,我计算了偏移量,并将阵列向上移动了那么多:

int offset = (4 - (uintptr_t)(memory) % 4) % 4;
memory += offset;

做完这些之后,一切又如预期的那样。