如何调试分段错误?

时间:2015-03-29 01:56:37

标签: c++ segmentation-fault iostream

在循环中,我将每个元素设置为0或entry_count-1时,它都有效。 当我设置它以使entry_count很小时,它工作,我用手写而不是循环(sorted_order [0] = 0; sorted_order [1] = 1; ...等)。

请不要告诉我如何修复我的代码。由于非常具体的原因,我不会使用智能指针或向量。而是专注于这个问题: 什么样的条件会导致这个段错误? 谢谢。

---- OLD -----

我正在尝试调试不能在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调试我发现它必须在循环中。

接下来我想知道段错误发生在循环中有多远,所以我补充道:

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

它显示了整个范围,它被认为是循环并且没有段错误。

经过一些实验,我最终在循环之前创建了一个字符串流,并在循环的每次迭代中为其写入一个空字符串,并且没有段错误。

我尝试了一些其他各种各样的操作,试图弄清楚发生了什么。我尝试设置变量j = i;和那样的东西,但我没有发现任何有用的东西。

运行valgrind我在segfault上获得的唯一信息是它是一个“常规保护错误”和一些关于11的默认响应。它还提到有条件跳转或移动取决于未初始化的值,但是看着代码我无法弄清楚这是怎么可能的。

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

4 个答案:

答案 0 :(得分:3)

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

但是正如您在问题中提到的那样,您可以使用 Valgrind 附加您的程序,因为它可重现。所以你可能想附上你的程序(a.out)。

  

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

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

一旦你能够弄清楚你的第一个错误,修复它并重新运行它,看看你得到的其他错误。这个步骤应该完成,直到Valgrind没有报告错误。

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

答案 1 :(得分:2)

Valgrind和GDB非常有用。

我之前使用的最前一个是GDB-我喜欢它,因为它向我显示了Segmentation Fault所在的确切行号。

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

GDB Tutorial 1

GDB Tutorial 2

如果你仍然无法弄清楚如何在这些教程中使用GDB,那么谷歌就有很多!只需使用GDB搜索调试分段错误!

祝你好运:)

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

由于某种原因,机器会出现未对齐访问的段错误。也就是说,我写的整数没有被写入四个字节的倍数的内存边界。在循环之前,我计算了偏移并将数组向上移动了很多:

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

完成此操作后,所有事情都表现得如预期一样。

相关问题