【问题标题】:How to debug segmentation fault?如何调试分段错误?
【发布时间】:2015-03-29 01:56:36
【问题描述】:

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

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

---- 旧 -----

我正在尝试调试无法在 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;
}

循环中的某处似乎存在段错误。不幸的是,切换到调试模式会使段错误停止。使用cout调试发现一定是在循环中。

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

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

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

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

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

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

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

【问题讨论】:

  • 调试器告诉你什么?你怎么知道块足够大?它是如何分配的?从那时起entry_count 会发生变化吗?你为什么不使用std::vector
  • 我们需要查看更多代码。假设int* memory = new int[entry_count],那么一切都应该没问题。或者,在 gdb 中加载 core 文件并向我们展示 wherebt full 的输出。最后,您应该使用new 或更好的std::vector
  • 如果您对memory 的假设是正确的,那么您提供的代码中的任何内容都不应出现段错误。我建议使用std::vector,它将在良好的调试编译器上进行边界检查,并可能立即显示您的问题。
  • @MikeSeymour 有没有理由使用原始指针来存储数组?
  • @Golazo 不,因为 C++ 和 C 是不同的语言,这个问题是关于 C++ 的。

标签: c++ segmentation-fault iostream


【解决方案1】:

这显然是您的程序中使用无效内存的症状。通过查看您的代码 sn-p 很难找到这点,因为它很可能是已经发生的其他不良事件的副作用。

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

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

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

一旦你能够找出你的第一个错误,修复它并重新运行它,看看你遇到了什么其他错误。应该完成这些步骤,直到 Valgrind 没有报告任何错误。

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

【讨论】:

    【解决方案2】:

    Valgrind 和 GDB 非常有用。

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

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

    GDB Tutorial 1

    GDB Tutorial 2

    如果您仍然无法通过这些教程了解如何使用 GDB,那么 Google 上有很多内容!只需搜索使用 GDB 调试分段错误!

    祝你好运:)

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 您是否使用 memgrind 进行边界检查? Memcheck Memcheck 检测内存管理问题,主要针对 C 和 C++ 程序。当程序在 Memcheck 的监督下运行时,会检查所有内存的读写,并拦截对 malloc/new/free/delete 的调用。因此,Memcheck 可以检测您的程序是否...
      • 我从未听说过。我使用 memcheck,这是我设置的唯一选项。
      • 有很多选项Memcheck: a memory error detector。我发现 --malloc-fill 和 --free-fill 很有用。另外,如果您可以发布 mc 报告会有所帮助。
      【解决方案4】:

      经过几天的实验,我弄清楚了到底发生了什么。

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

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

      执行此操作后,一切都再次按预期运行。

      【讨论】:

        猜你喜欢
        • 2023-03-23
        • 2016-09-07
        • 2013-01-06
        • 2013-05-19
        • 2012-01-06
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 2012-05-11
        相关资源
        最近更新 更多