当前位置: 首页 > 知识库问答 >
问题:

在gcc中禁用if(0)消除

鲁鸿
2023-03-14

如果(0)块,我如何防止GCC消除里面的代码?

当我使用Visual Studio时,我的调试技巧之一是在程序中放入如下代码

if (0)
    do_some_debug_printing_and_checking();

然后,当遇到断点时,我单击do_some_debug_printing_and_checking()行,选择“设置下一个语句”并强制执行。

当我使用gcc/gdb作为后端时,“setnext语句”不再有效,因为gcc只是从if(0)语句中删除代码。

我当然使用-O0标志来禁用优化。我也尝试过-fno-dce-fno-tree-dce标志来显式禁用死代码消除,但没有效果:if(0)的内容只是不存在于二进制文件中,我不能使用set Next语句跳转到其中。

有没有什么好方法告诉gcc禁用if(0)内容的消除?

编辑:

感谢"附加变量"解决方案,但有2件事我不喜欢它:

  1. 这仍然是一行额外的代码
  2. 当我构建发布版本并确实希望那些调试内容消失时,它不会自动优化。当然我可以使用#ifdef-s,但这需要更多额外的行

真的,绝对没有办法让海湾合作委员会保留那个死代码?

共有2个答案

徐昕
2023-03-14

我不会依赖gcc编译器标志来完成这项工作。编译器标志可以在不同版本的gcc之间更改,也可以在不同的编译器之间更改。您可能会发现自己需要在六个月内在Visual C中调试相同的代码。。。

@CharlesBailey为如何使用extern变量提供了一个很好的建议。这里有一个替代方案,它不需要将变量暴露于整个模块或保存在静态存储中。

if语句的作用域中声明临时变量易失性

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时,本地变量将被创建、声明为volatile并保留。当您将IS_debugation定义为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
阴宏爽
2023-03-14

最简单的方法是使检查依赖于(比如说)一个具有外部链接的变量

例如。

extern bool debug;
if (debug)
    do_some_debug_printing_and_checking();

在命名空间范围的某处:

bool debug = false;
 类似资料:
  • 该项目使得 Android NDK 平台支持 Objective C 2.0,安装方法如下: mkdir build cd build ../configure --prefix=/usr/local/android --target=arm-android-eabi --disable-werror make make install

  • 问题内容: List listStr = new ArrayList (); 与 在我看来,使用的好处之一是它不检查列表的大小,然后将其与零进行比较,它只是检查列表是否为空。是否有任何其他的优点,因为我经常看到的,而不是在代码库?是否存在我不知道以这种方式检查的原因? 问题答案: 基本上,在某些列表的实现中,该方法检查大小是否为零(因此从性能的角度来看,它们实际上是等效的)。但是,在其他类型的列表

  • 问题内容: 即使使用标志,我也无法禁用它。如何禁用它? 问题答案: 您可以使用编译器标志为可变长度数组生成错误:

  • 本文向大家介绍if(a-b <0)和if(a 相关面试题,主要包含被问及if(a-b <0)和if(a 时的应答技巧和注意事项,需要的朋友参考一下 并且可能意味着两个不同的东西。考虑以下代码: 运行时,将仅打印。发生的事情显然是错误的,但是溢出并变为,这是负面的。 话虽如此,请考虑一下数组的长度确实接近。中的代码如下所示: 确实接近,所以(是)可能溢出并变成(即负数)。然后,将 下溢 相减回正数。

  • 问题内容: 平台之间可能有所不同,但是 当我使用gcc编译并运行下面的代码时,每次在ubuntu 11.10中获得0。 为什么即使有calloc,malloc的行为也是如此? 难道就意味着即使您不希望有时将值初始化为0,也会有不必要的性能开销吗? 编辑:哦,我以前的示例不是初始化,而是碰巧使用“新鲜”块。 我恰恰在寻找的是为什么它在分配一个大块时将其初始化: 但是,感谢您指出进行分配时存在安全原因

  • 我认为这非常简单,但我似乎找不到答案。 我正在编写一个IF语句,但测试是对象是否返回一个值。我不确定如何处理语句中的。 假设<代码>测试 它似乎仍然不起作用.....