为什么调试器不知道#define'd常量?

Mic*_*ick 26 c++ debugging visual-studio-2015

在调试我的代码时,我经常想知道#defined'd常量的值.但调试器似乎并不知道它们的值.这意味着我必须围绕查看包含路径等来查找#define行.是否有一些技巧可以让这更容易?

更新:我不得不向Tony D授予绿色标记以详细回答标题问题,但我也赞成使用const而不是#define(我也测试了它enum也有效).最后使用F12找到原来的#define线是另一个好主意.

Ton*_*roy 42

对于谷歌价值的10分钟,似乎Visual Studio不支持这一点.

有些编译器会尝试这样做,但有一个原因是它有点脆弱/尽力而为......

首先重新发布并删除对此的常见但虚假的解释:在"正确"编译开始之前,有一个概念上不同的预处理步骤替代文本用于预处理器宏的使用,但实际上没有理由预处理阶段无法传递记录的#define#undef起纳入与其他调试信息INE语句.

什么痛苦是直觉上和通常认为" - #define预处理器常数"不是什么...

const Some_Type some_identifier = some_value;
Run Code Online (Sandbox Code Playgroud)

......因为后者在应用程序的命名空间层次结构的特定位置,真的不能改变,而一个#define可以#undef-ined并重新#defined任意次数,使得"价值"预处理宏在特定的代码行可以取决于该行如何包含在翻译单元中:每个翻译单元中每个包含相同行的行可以具有该宏的不同值(或没有值).

出于这个原因,在通过某些代码调试时显示宏的"值"是有问题的 - 它只保证在特定转换单元中的特定行上具有单个值,但程序员通常希望调试器显示和导航程序根据源文件中的行.

考虑:

use_x.h

class T ## X {
    void g() { ... }
};
Run Code Online (Sandbox Code Playgroud)

some_app.cc

#define X 2783
#include "use_x.h"
#undef X
#define X 2928
#include "use_x.h"
void f() {
    const int last_x = X;
}
Run Code Online (Sandbox Code Playgroud)

如果您的调试器通过f()上面的步骤,X可以说是2928,但是如果您逐步完成一个版本g()- 调试器会很难理解类名和X用于创建它的值之间的某种联系,或者找出以其他方式展示的内容....

如果你将鼠标悬停在宏上而停在其他行 - 可能是从不同的翻译单元链接 - 会变得更糟 - 调试器无法知道你是否对该宏的最后一个值感兴趣执行已经通过,或者执行继续时可能具有的下一个值(如果它甚至可以预测可能首先发生的任何分支),或者调试器停止的行处宏的值(如果有的话).

因此,一些工具链(编译器/调试信息编码/调试器)只是不买这个烂摊子.更好的工具可能会跟踪简单的案例,然后不会显示任何内容 - 或者可能的值列表 - 用于分析过于复杂的案例.显示错误的值比没有更糟糕.


它在调试器中没有帮助,但是当需要查看宏值/替换时,您可以尝试cl /E(对于GCC/clang选项-E)为翻译单元提供预处理输出 - 然后您可以看到已经进行了哪些替换.预处理.


Lig*_*ica 16

在编译之前,预处理器会对宏进行评估和解析.这不仅仅是编译的程序不知道它们的值:编译的程序根本不包含它们的痕迹.您的调试器无需检查.

将宏视为代码生成工具,一切都将变得清晰.

某些编译器确实有一个标志,您可以设置该标志以保留各种预处理器定义的值,并将它们列在可执行文件的特殊区域中以进行调试.不过,我不知道如何在VS中实现这一点.我反而使用相关的开关运行预处理程序,然后检查结果.