是什么导致了 C++ 中的段错误? STL列表节点内存分配?
我编写了一些 C++ 代码,在我的笔记本电脑上运行得非常好(在 Microsoft 编译器和 MinGW 下的 g++ 下编译)。我正在将它移植到 Unix 机器上。
我在 Unix 机器上使用 g++ 和 Intel 的 ipcp 进行编译,在这两种情况下,我的程序在运行一段时间后都会崩溃(段错误)。我可以运行它很短的时间而不会崩溃。
当我调试时,我发现当程序尝试复制 STL 列表时会发生崩溃 - 具体来说,当程序尝试分配内存以在列表中创建新节点时会发生崩溃。我在调试器(TotalView)中收到的错误是“分配调用失败或返回的地址为空”。
每次运行代码时,崩溃并不总是发生在代码中的同一位置,但总是发生在 STL 列表中创建节点的分配调用期间。我不认为我的内存不足。我有一些内存泄漏,但它们非常小。还有什么可能导致内存分配错误?为什么它发生在 Unix 机器上而不是我的 PC 上?
更新:我使用 MemoryScape 来帮助调试。当我使用保护块时,程序运行完毕而没有崩溃,这进一步表明存在内存问题。最终解决问题的方法是“绘制”分配的内存。事实证明,我正在初始化一个变量,但在将其用作数组索引之前没有将其设置为值。因此,数组会溢出,因为它使用了变量内存位置中的任何垃圾——通常是 0 或其他一些小数字,所以没有问题。但是,当我运行该程序足够长的时间时,当我写入数组越界时,它更有可能保存更大的数字并损坏堆。用大数字绘制分配的内存会在我尝试在数组中写入值的代码行处强制出现段错误,并且我可以看到大绘制数字被用作数组索引。
I've written some C++ code that runs perfectly fine on my laptop PC (compiled under both a Microsoft compiler and g++ under MinGW). I am in the process of porting it to a Unix machine.
I've compiled with both g++ and with Intel's ipcp on the Unix machine and in both cases, my program crashes (segfaults) after running for a while. I can run it for a short time without a crash.
When I debug, I find that the crash is happening when the program tries to copy an STL list - specifically, it happens when the program tries to allocate memory to create a new node in the list. And the error I get in the debugger (TotalView) is that "an allocation call failed or the address returned is null."
The crash does not always happen in the same place in the code each time I run it, but does always happen during an allocation call to create a node in an STL list. I don't think I'm running out of memory. I have a few memory leaks, but they're very small. What else can cause a memory allocation error? And why does it happen on the Unix machine and not on my PC?
UPDATE: I used MemoryScape to help debug. When I used guard blocks, the program ran through without crashing, further suggesting a memory issue. What finally worked to nail down the problem was to "paint" allocated memory. It turns out I was initializing a variable, but not setting it to a value before I used it as an array index. The array was therefore overrunning because it was using whatever garbage was in the variable's memory location -- often it was 0 or some other small number, so no problem. But when I ran the program long enough, it was more likely to hold a larger number and corrupt the heap when I wrote out of bounds of the array. Painting the allocated memory with a large number forced a segfault right at the line of code where I attempted to write a value in the array and I could see that large painted number being used as the array index.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可能是由堆损坏引起的 - 在代码的其他地方,您正在覆盖释放的内存,或者写入内存分配范围之外的内存(缓冲区溢出,或在分配的内存开始之前写入)。堆损坏通常会导致不相关位置崩溃,例如 STL 代码。由于您使用的是 unix 平台,因此您应该尝试在 valgrind 下运行您的程序,以尝试识别原始堆损坏。
This is likely caused by heap corruption - elsewhere in the code, you're overwriting freed memory, or writing to memory outside the bounds of your memory allocations (buffer overflows, or writing before the start of allocated memory). Heap corruption typically results in crashes at an unrelated location, such as in STL code. Since you're on a unix platform, you should try running your program under valgrind to try to identify the original heap corruption.
这听起来像是动态内存分配数据结构的损坏,这通常是由其他不相关的代码引起的。这种类型的错误因在没有外部工具的情况下很难发现和重现而臭名昭著,因为内存布局的任何变化都可以掩盖它。它在 Windows 版本中可能是靠运气而成功的。
内存调试器是捕获此类损坏的好工具。
valgrind
、dmalloc
和efence
是检查程序正确性的非常好的替代方法。This sounds like a corruption of the dynamic memory allocation data structures, which is often caused by other, unrelated code. This type of bug is notorious for being hard to find and reproduce without external tools, because any change in memory layout can mask it. It probably worked through luck in the Windows version.
Memory debuggers are great tools to catch such corruption.
valgrind
,dmalloc
andefence
are very good alternatives to check the correctness of your program.好吧,如果你运行它一段时间,那么它最终会占用大量内存。这就是关于泄漏的事情。您应该记录崩溃时的内存使用情况,以查看是否有可用内存。
Well, if you run it for a while, then it ends up being a lot of memory. That's kind of the thing about leaks. You should log your memory usage at the point of the crash to see if there was any memory available.