C语言 堆栈损坏;跨函数调用存储在寄存器中的变量应该发生什么情况



我一直在追查似乎是由于内存损坏而导致的崩溃。设置为 C,使用 适用于 iOS 的 llvm 构建。

在调试模式和优化级别为 0 (-O0( 时不存在内存损坏。为了能够单步执行代码,我使用调试符号但优化级别 1 (-O1( 进行了重建。这足以重现崩溃,它允许我逐步完成程序。

我已经将问题缩小到特定的函数调用。在它之前,某个指针的值是正确的。在它之后,该值被损坏(它最终等于0x02,无论它的价值如何(。

Lldb似乎不想监视变量或内存位置。切换到 gdb,我发现如果我尝试打印上述变量的地址,我会遇到以下消息:"寄存器 $r 4 中的标识符'x'请求的地址"。

我知道,作为一种优化,编译器可能会决定将变量的值保留在寄存器中。确实如此,如果我在函数调用之前和之后打印 $r 4 的值,我会在函数调用之前和之后看到正确的值0x02。

在这一点上,我有点头疼,不知道如何将其拆分为较小的问题。因此,我的问题是:

  1. 假设编译器将变量的值存储在寄存器中作为优化,那么当调用另一个函数时,该寄存器会发生什么?

  2. 是否有某种机制可以在新函数返回后存储和恢复值?

  3. 对调试技术有什么建议吗?

所有的帮助和建议都表示赞赏。关于该主题的阅读材料的链接也非常受欢迎。

谢谢


编辑:添加版本信息

iOS版本:5.1

LLVM 版本: i686-Apple-Darwin10-LLVM-GCC-4.2 (GCC( 4.2.1 (基于 Apple Inc. build 5658( (LLVM build 2377.00(

Xcode 版本:4.3.1

Gdb 版本: GNU gdb 6.3.50-20050815 (苹果版本 gdb-1708(

在iPhone 3Gs上运行(模拟器中不会出现崩溃(

不是完整的答案,但是

假设编译器将变量的值存储在 注册为优化,应该会发生什么 调用另一个函数时注册?

寄存器可能应该由被调用方推送到堆栈。

是否有某种机制可以存储和恢复一次值 新函数返回?

取决于调用约定,但一般来说 - 将其推送到堆栈的人负责将其从堆栈中弹出

最后一件事:

如果您遇到这种情况,即"它在某些优化级别上有效",而在其他优化级别上不起作用,那么您很可能有未定义的行为。如果你在代码中找不到它,你可以在这里询问它,给出实际的代码。

如果可能的话,尝试使用Valgrind。这看起来是一个很好的起点。

另外,请尝试为您的程序启用 -fstack-protector。

相关内容

最新更新