setjmp 和省略帧指针

Posted

技术标签:

【中文标题】setjmp 和省略帧指针【英文标题】:setjmp and omit frame pointer 【发布时间】:2011-05-04 17:39:44 【问题描述】:

我一直试图在我的代码(它使用 setjmp)中找到一个间歇性崩溃错误,并将其缩小为:使用 /O2 编译时出现,使用 /O2 /Oy- 时消失,即只显示向上省略帧指针。

http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspx 建议 setjmp 需要一个帧指针。因此:

    似乎当使用 /O2 编译使用 setjmp 的程序时,Visual C++ 会静默生成导致间歇性堆栈损坏的代码。这是真的吗,还是我错过了什么?

    在我看来,只有调用 setjmp 的函数才需要用帧指针编译,程序的其余部分——甚至是调用 longjmp 的函数——应该可以忽略帧指针。这是真的吗?

编辑:我进一步缩小了范围。

在调用 setjmp 的函数上启用帧指针没有任何区别,但那是因为编译器已经按照它应该的方式执行此操作,显然注意到它需要完成,并自动执行。

真正有所作为的是在 main.js 上启用了帧指针。这并不像听起来那么奇怪,因为崩溃是从 main 的回报中体现出来的。现在我想到了,我可以在谷歌快速搜索 setjmp 用法中找到的所有示例,在 main.js 中执行。也许碰巧微软编译器团队只是这样测试它。

这是使用它的惯用方式,也许对我来说最好的解决方法是将 setjmp-using 函数内联到 main 中。

【问题讨论】:

这听起来像是 MSVC 中的一个错误。我无法理解您将如何实现setjmp/longjmp 在没有帧指针时失败。看来您必须竭尽全力才能使它们破碎。无论如何,我只是全局启用帧指针;它对性能没有太大影响。 崩溃的调用栈是什么? 嗨,我想说这个错误仍然存​​在。参见 gcc 邮件列表的讨论:gcc.gnu.org/ml/gcc/2011-10/msg00253.html 您能发布导致此问题的代码吗?我想我在 MSVC10 中看到了同样的问题,关闭 Omit Frame Pointers 解决了它,但我想分析程序集以确定。 @syplex 我当然可以给你代码,但发布起来有点棘手,因为它需要在多个文件中才能阻止编译器通过内联函数破坏测试,如果你联系我的话russell.wallace (at) gmail (dot) com 我可以发给你。 【参考方案1】:

好的,我已经发布了一个带有独立测试用例的错误报告,因此希望修复正在酝酿中:http://connect.microsoft.com/VisualStudio/feedback/details/666704/visual-c-generates-incorrect-code-with-omit-frame-pointer-and-setjmp

与此同时,解决方法是不要使用省略帧指针,或者将调用 setjmp 的代码放在 main 中,或者将调用 longjmp 的函数与调用 setjmp 放在同一个源文件中。

【讨论】:

【参考方案2】:

您能否详细说明有关崩溃本身的信息?我的意思是,编译器为longjmp 生成的代码是在longjmp 之后立即发生的,还是当您尝试访问自动变量时,或者当您尝试退出函数时?

我猜target函数必须用标准栈帧编译,使用longjmp的函数似乎没有合理的限制。

【讨论】:

崩溃发生在从 main 返回时,在 setjmp-ing 函数有一个帧指针但 main 没有的情况下。让我知道您是否需要测试用例的副本,如果需要,通过什么媒介;或者如果您想自己创建一个,要记住的关键是 setjmp-ing 和 longjmp-ing 函数必须在单独的翻译单元中。【参考方案3】:

setjmp 以许多不同的方式实现,但这可能与特定操作系统的程序集实现有关。

当使用 __stdcall 编译函数时,参数存储相对于帧指针。您的实现可能正在访问相对于所述指针的 setjmp 的参数,因此它不必丢弃多个寄存器,将上下文保存到它们(因为这会破坏 setjmp 的大部分要点);我似乎记得 setjmp 在 linux 内核中是这样实现的。

当然,如果 msvc 不生成设置 ebp 的指令,那么这将不起作用,肯定会导致崩溃。

【讨论】:

以上是关于setjmp 和省略帧指针的主要内容,如果未能解决你的问题,请参考以下文章

函数指针玩得不熟,就不要自称为C语言高手(函数指针是解耦对象关系的最佳利器,还有signal)

GCC帧指针的开启与关闭以及反汇编测试

使用 OpenCV 将视频帧读取到指定的指针(C++)

对数据帧火花执行操作时出现空指针异常

Linux - 函数的栈帧

从(视频)帧英特尔实感获取 RGB 值时出现指针异常