在 gcc 中禁用"if(0)"消除
Disable "if(0)" elimination in gcc
如何防止 GCC 消除 if(0) 块中的代码?
当我使用Visual Studio时,我的调试技术之一是将这样的代码放在我的程序中:
if (0)
do_some_debug_printing_and_checking();
然后,当遇到断点时,我单击 do_some_debug_printing_and_checking() 行,选择"设置下一个语句"并强制执行。
当我使用 gcc/gdb 作为后端时,"set next 语句"不再起作用,因为 gcc 只是从 if(0) 语句中删除了代码。
我当然使用 -O0 标志来禁用优化。我也尝试了 -fno-dce -fno-tree-dce 标志来显式禁用死代码消除,但它没有效果:if(0) 的内容只是在二进制文件中不存在,我无法使用 set next 语句跳转到它。
有什么好方法可以告诉 gcc 禁用 if(0) 内容的消除?
编辑:
感谢您的"附加变量"解决方法,但是有两件事我不喜欢它:
- 它仍然是一行额外的代码
- 当我构建发布版本并希望这些调试内容消失时,它不会自动优化。当然,我可以使用 #ifdef-s,但这甚至是更多的额外行。
真的,绝对没有选择让 GCC 保留死代码?
最简单的方法是使检查依赖于(例如)具有外部链接的变量。
例如
extern bool debug;
if (debug)
do_some_debug_printing_and_checking();
命名空间范围内的某个地方:
bool debug = false;
我不会依赖 gcc 编译器标志来做到这一点。 编译器标志可以跨 gcc 版本更改,并且可以跨编译器更改。 您可能会发现自己需要在六个月内在 Visual C++ 中调试相同的代码......
@CharlesBailey 对如何使用 extern
变量执行此操作提出了很好的建议。 这里有一种不需要向整个模块公开变量或保存在静态存储中的替代方法。
在 if
语句的作用域中声明一个临时变量volatile
:
if (volatile bool dbg = false)
{
do_some_debug_printing_and_checking();
}
这使得临时变量的范围非常窄。 volatile
限定符不允许编译器假设有关变量的任何内容,也不会优化分支。
要记住的一件事是,变量始终在堆栈上分配,并将保留在堆栈上,直到函数退出。 这种方法和extern
方法都应该有效,但权衡略有不同(可能可以忽略不计)。
如果您愿意使用宏来帮助解决此问题,那么您可以在将代码发布到生产环境时轻松禁用临时变量:
#ifndef IS_DEBUGGING
# define IS_DEBUGGING 0
#endif
#if IS_DEBUGGING
# define TMP_DBG_FLAG volatile bool dbg_flag = false
#else
# define TMP_DBG_FLAG false
#endif
然后将您的if
语句声明为:
if ( TMP_DBG_FLAG )
{
do_some_debug_printing_and_checking();
}
将IS_DEBUGGING定义为 1 时,将创建局部变量、声明为易失性并保留局部变量。 将IS_DEBUGGING定义为 0 时,宏将扩展到常量false
,编译器将优化分支。 对于extern
方法,也可以做一些非常类似的事情。
这几行额外的代码,但它们与你使用TMP_DBG_FLAG的次数无关。 该代码也比使用大量ifdef
更具可读性。 可以使宏更安全一些(通过将 __LINE__
的值附加到它),但这需要三个宏,并且可能不是必需的:
#if IS_DEBUGGING
// paste symbols 'x' and 'y' together
# define TMP_DBG_FLAG_SYMCAT0(x,y) x ## y
// need one level of indirection to expand __LINE__...
# define TMP_DBG_FLAG_SYMCAT(x,y) TMP_DBG_FLAG_SYMCAT0(x,y)
# define TMP_DBG_FLAG volatile bool TMP_DBG_FLAG_SYMCAT(dbg_flag_,__LINE__) = false
#else
# define TMP_DBG_FLAG false
#endif
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 如何在BST的这个简单递归实现中消除警告
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何删除peer if else分支中的冗长句子
- 我似乎对if/else的基本语句有问题:/
- if数组上的随机数
- 将按位if条件转换为普通if条件
- If语句在c++中被忽略
- 比较if语句中的数组值和int值
- 需要消除这些"else if"并优化代码
- 使用 "else if" 是否消除了在 while 循环中的每个条件后休息的需要?
- 在 gcc 中禁用"if(0)"消除