【问题标题】:What causes a segfault in C++ STL list node memory allocation?是什么导致 C++ STL 列表节点内存分配中的段错误?
【发布时间】:2012-01-27 01:16:55
【问题描述】:

我编写了一些在我的笔记本电脑上运行良好的 C++ 代码(在 Microsoft 编译器和 MinGW 下的 g++ 下编译)。我正在将它移植到 Unix 机器上。

我在 Unix 机器上使用 g++ 和 Intel 的 ipcp 进行了编译,在这两种情况下,我的程序在运行一段时间后都会崩溃(段错误)。我可以在短时间内运行它而不会崩溃。

当我调试时,我发现当程序尝试复制 STL 列表时发生崩溃 - 具体来说,当程序尝试分配内存以在列表中创建新节点时发生崩溃。我在调试器(TotalView)中得到的错误是“分配调用失败或返回的地址为空”。

每次我运行它时,崩溃并不总是发生在代码中的同一位置,但总是在分配调用以在 STL 列表中创建节点时发生。我不认为我的内存不足。我有一些内存泄漏,但它们非常小。还有什么可能导致内存分配错误?为什么它发生在 Unix 机器上而不是我的 PC 上?

更新:我使用 MemoryScape 来帮助调试。当我使用保护块时,程序运行并没有崩溃,进一步表明存在内存问题。最终解决问题的是“绘制”分配的内存。事实证明,我正在初始化一个变量,但在将其用作数组索引之前没有将其设置为一个值。数组因此溢出,因为它使用了变量内存位置中的任何垃圾——通常是 0 或其他一些小数字,所以没问题。但是当我运行程序足够长的时间时,当我写出数组的边界时,它更有可能保存一个更大的数字并破坏堆。用大数字绘制分配的内存会在我尝试在数组中写入值的代码行中强制出现段错误,我可以看到这个大的绘制数字被用作数组索引。

【问题讨论】:

  • segfaults 的可能原因有很多,不仅不可能在这里全部发布,而且没有任何意义,因为它不会导致任何地方。如果 otoh 你会发布一些不错的测试用例,我们可以告诉更多。
  • 既然你是在 Unix 上,那就抓住机会试试 Valgrind,它对解决内存问题很有帮助。
  • 查看代码片段会很有帮助。但是,如果您遇到内存分配问题,首先要检查的事情之一是您的程序是否泄漏。您是否查看过进程的内存消耗?
  • 暂时可以验证一下crash是不是std::bad_alloc传播出main造成的。
  • 需要看代码。但这通常意味着您正在写一些内存结构。调高编译器的警告级别并确保有 0 个警告(这可能会有所帮助)。

标签: c++ memory stl porting allocation


【解决方案1】:

这可能是由堆损坏引起的 - 在代码的其他地方,您正在覆盖已释放的内存,或者写入内存分配范围之外的内存(缓冲区溢出,或在分配的内存开始之前写入)。堆损坏通常会导致在不相关的位置崩溃,例如在 STL 代码中。由于您在 unix 平台上,您应该尝试在 valgrind 下运行您的程序以尝试识别原始堆损坏。

【讨论】:

    【解决方案2】:

    这听起来像是动态内存分配数据结构的损坏,这通常是由其他不相关的代码引起的。这种类型的错误因在没有外部工具的情况下很难找到和重现而臭名昭著,因为内存布局的任何更改都可以掩盖它。它可能在 Windows 版本中很幸运。

    内存调试器是捕捉此类损坏的绝佳工具。 valgrinddmallocefence 是检查程序正确性的非常好的选择。

    【讨论】:

      【解决方案3】:
       I have a few memory leaks, but they're very small.
      

      好吧,如果你运行它一段时间,那么它最终会占用大量内存。这就是关于泄漏的事情。您应该在崩溃时记录您的内存使用情况,以查看是否有任何可用内存。

      【讨论】:

      • 谢谢你的想法,但我提到它们很小,因为我一直运行程序,消耗的总内存只有几K。内存工具显示还有内存可用,所以我不认为我的内存不足。
      • 如果可疑代码在循环中执行,最终只会占用大量内存。如果它在启动时泄漏了 8 个字节并且不再调用该代码,那么程序无论运行多长时间都只会泄漏 8 个字节。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 2021-09-14
      • 2020-09-15
      • 2012-04-19
      相关资源
      最近更新 更多