当使用 -fomit-frame-pointer 时(自动用于各种 -O 设置),执行回溯是有问题的。我想知道是否有办法在编译时确定代码是用这个开关编译的?在这种情况下,我可以放入一个#ifndef 以防止在不明智的情况下进行回溯。
当这个 -fomit-frame-pointer 开关打开时,是否设置了任何宏?
谢谢,
SetJmp
我刚试过这个:
gcc -E -fomit-frame-pointer -Wp,-dM foo.c > fpo.out gcc -E -Wp,-dM foo.c > no-fpo.out diff no-fpo.out fpo.out
其中 foo.c 是一个简单的“Hello World”程序,但没有得到任何结果。这意味着所有预处理器宏都是相同的,无论是否-fomit-frame-pointer
使用。所以我认为你的问题的答案是“不”。
可能您能做的最好的事情就是修改您的 Makefile(或您的构建过程使用的任何内容)以在-DNO_FRAME_POINTERS
使用-fomit-frame-pointer
.
你不能在编译时这样做,但在运行时你可以检查你的程序是否优化。
编写一个肯定会被优化器更改的代码,例如将非易失性变量与setjmp
/混合longjmp
,通过该变量的值,您将知道您的程序是否经过优化。
#include <setjmp.h>
#include <stdio.h>
int is_optimised(void) {
int i = 1;
jmp_buf jmp_loc;
if (setjmp(jmp_loc)) {
return i; // optimiser changes it to "return 1"
}
i = 0;
longjmp(jmp_loc, 1);
return 0;
}
int main(int argc, char *argv[]) {
printf("%soptimised\n", is_optimised() ? "" : "non-");
return 0;
}
-O
如果在没有开关的情况下使用 GCC 编译,它会打印“ non-optimised
”,切换-O1
到-O4
它会打印“ optimised
”。
当然,您的里程(使用其他编译器)可能会有所不同。
至于检查,在运行时检查 ebp 寄存器(根据您的体系结构调整)是否指向堆栈顶部以下的几个字节,然后是否遵循存储在 [ebp] 中的指针是否有意义。