如何防止GCC消除 if(0) 块内的代码?
当我使用Visual Studio时,我的一种调试技巧是将这样的代码放在我的程序中:
if (0)
do_some_debug_printing_and_checking();
然后,当一个断点被击中时,我点击 do_some_debug_printing_and_checking() 行,选择"set next statement"并强制它执行 .
当我使用gcc / gdb作为后端时,"set next statement"不再起作用,因为GCC只是从 if(0) 语句中删除代码 .
我当然使用 -O0 标志来禁用优化 . 我也尝试了 -fno-dce -fno-tree-dce 标志来显式禁用死代码消除,但它没有效果: if(0) 的内容在二进制文件中不存在,我不能使用 set next statement 跳转到它 .
有没有什么好方法告诉gcc禁用 if(0) 内容的删除?
编辑:
感谢“附加变量”解决方法,但有两件事我不喜欢它:
-
这还是一行额外的代码
-
它赢得了更多的额外线条 .
真的,绝对没有选择让GCC保留死代码吗?
2 回答
最简单的方法是使检查依赖于(比如)具有外部链接的变量 .
例如 .
在命名空间范围的某处:
我不会依赖gcc编译器标志来做到这一点 . 编译器标志可以在gcc版本之间进行更改,并且可以在编译器之间进行更改 . 您可能会发现自己需要在Visual C中六个月内调试相同的代码...
@CharlesBailey对如何使用
extern
变量做了一个很好的建议 . 这里's one alternative that doesn' t要求变量暴露给整个模块或保存在静态存储中 .在
if
语句的范围内声明临时变量volatile
:这使临时变量的范围非常窄 .
volatile
限定符不允许编译器假设有关变量的任何内容,或者优化分支 .要记住的一件事是变量总是在堆栈上分配,并且将保留在堆栈中,直到函数退出 . 这种方法和
extern
方法都应该有效,但是有一些不同(可能是可以忽略不计)的权衡 .如果您愿意使用宏来帮助解决此问题,那么在将代码发布到 生产环境 环境中时,可以轻松禁用临时变量:
然后将
if
声明声明为:将IS_DEBUGGING定义为1时,将创建局部变量,声明为volatile并保留 . 当您将IS_DEBUGGING定义为0时,宏将扩展为常量
false
,并且编译器会优化分支 . 也可以为extern
方法做一些非常相似的事情 .这几行额外的代码,但它们与您使用TMP_DBG_FLAG的次数无关 . 该代码比使用大量的
ifdef
更易读 . 可以使宏更安全(通过向它附加__LINE__
的值),但这需要三个宏,并且可能不是必需的: