C/C++程序中的损坏堆栈问题
Posted
技术标签:
【中文标题】C/C++程序中的损坏堆栈问题【英文标题】:Corrupt stack problem in C/C++ program 【发布时间】:2011-04-14 18:40:21 【问题描述】:我在 linux 服务器上运行一个 C/C++ 程序来提供视频。该程序(比如名为插件)的核心功能是转换视频,我们为每个视频请求分叉一个单独的插件进程。但是我遇到了一个奇怪的问题,有时服务器平均负载会出乎意料地高。我在这个阶段从 top 命令看到的是,有些进程运行了很长时间并占用了一些巨大的 CPU。
当我使用 gdb 和回溯堆栈调试这个正在运行的程序时,我发现了损坏的堆栈:“此帧内部的上一帧(损坏的堆栈?)”。我在网上搜索过,发现如果程序出现分段错误,就会发生这种情况。
但是我知道如果程序出现分段错误,程序应该在那时崩溃并退出。但令人惊讶的是,程序在分段错误后仍然运行。
这可能是什么原因?我知道程序中一定有一些大问题,但我就是不明白从哪里开始解决问题...如果你们中的任何人都可以给我看一些灯,那就太好了...
提前致谢
【问题讨论】:
可能损坏卡在您的情况下意味着您使用了不应该使用的内存位置。当类似的事情发生时,结果是未定义的行为。该程序注定不会崩溃。任何事情都可能发生。 【参考方案1】:附加调试器会改变进程的行为,因此您很可能无法获得可靠的调查结果。来自调试器的损坏的堆栈消息可能意味着特定的调试器无法理解二进制文件中的文本信息。
我建议随后在有问题的情况下运行 pstack 几次(这被称为“蒙特卡洛性能分析”)并附加 strace 或 truss 到有问题的地方,并检查进程在消耗 CPU 时所做的系统调用。
【讨论】:
【参考方案2】:在Valgrind 下运行您的程序并修复它发现的任何无效内存写入。
【讨论】:
嗨,Sam,您能否提供一些关于为什么程序在出现分段错误时仍会运行的信息?谢谢 @mahmudul 您可能遇到了未定义的行为,就是这样,未定义。【参考方案3】:某些优化,例如省略帧指针,会使调试器更难理解堆栈。
【讨论】:
【参考方案4】:如果你有代码,在调试中编译程序并在上面运行 Valgrind。
如果您没有代码,请联系程序的作者/提供者。
损坏的堆栈消息只是意味着代码对内存做了一些奇怪的事情。这并不意味着程序存在分段错误。此外,如果选择处理 SIGSEGV 信号,程序仍然可以运行。
如果通过分叉意味着您有一些进程会产生并运行其他较小的进程,则只需监视此类峰值并重新启动该进程即可。这假定您无权访问修复程序。
【讨论】:
【参考方案5】:可能会通过汇编代码操作对堆栈进行一些有趣的操作,例如真正的尾递归优化、自修改代码、不返回函数等,这可能会导致调试器无法正确返回- 跟踪堆栈并导致它触发损坏的堆栈错误,但这并不一定意味着内存已损坏......但肯定在幕后发生了一些非传统的事情。
【讨论】:
以上是关于C/C++程序中的损坏堆栈问题的主要内容,如果未能解决你的问题,请参考以下文章
混合模式 C++/CLI 崩溃:atexit 中的堆损坏(静态析构函数注册)