c++ 如何在VS中高效地调试宏?

1tuwyuhd  于 2023-02-14  发布在  其他
关注(0)|答案(9)|浏览(344)

我的(非托管)C++代码中有一个非常复杂的宏。有没有办法在VS调试器中扩展宏?或者有没有其他方法来调试宏?
例如,我想在其中放置一个断点。
(Yes,我知道宏是不好的。)

ukqbszuj

ukqbszuj1#

通过右键单击并转到属性,转到项目或源文件属性。在配置属性-〉C/C++-〉预处理器下,将生成预处理文件设置为带行号或不带行号,根据您的喜好而定。
这将显示您的宏在上下文中扩展到什么。如果您需要在实时编译的代码上调试它,只需剪切并粘贴它,并在调试时将其放在您的宏的位置。

unftdfkk

unftdfkk2#

我听到了关于这个主题的所有可能的否定答案:

  • 宏只能扩展而不能计算
  • 预处理器还应分析include文件
  • 嵌套宏可能过于复杂
  • 条件预处理可能很棘手
  • 宏是邪恶的,只是避免他们
  • 等等等等。

他们都是真的,但海事组织,他们与现实的日常编程碰撞。
事实上,在旧的C项目中,宏大多数只是作为函数使用,这对我来说至关重要。用/P生成所有预处理文件是可行的,但过于繁琐和耗时。我只是需要一个工具来扩展一个简单的宏,该宏定义在其他文件中的几行以上或最多几行。
如何做到这一点?
1.在Linux上,只需使用GDB及其扩展宏功能
1.在Windows上,我使用集成到Visual Studio中的https://www.jetbrains.com/resharper-cpp/
所以,是的,在实际意义上,这是可能的。

uwopmtnx

uwopmtnx3#

编译器很好地扩展了宏。得到一个宏扩展后的编译列表。
将扩展的宏插入到你的代码中。重新编译,你应该能够逐步通过它,做一个简单的测试。
一般来说,当我构建一个复杂的宏时,我会先硬编码,然后测试,再把它变成一个宏。
对于2008年,this可能会有所帮助

8ulbf1ek

8ulbf1ek4#

我从http://www.codeproject.com/Tips/320721/Macro-expansion-in-VCplusplus学到了调试宏的最佳方法。
我所做的是创建一个名为“test.cxx”的cxx文件,在里面我只放了宏和test.cxx的一些使用示例:

#define GetMacro(param1) \
  public: void Get##param1(){ return m_##param1; }

GetMacro(MyVariable);

在命令行中输入:

c:\ cl /EP test.cxx > output.cxx

当我打开输出.cxx文件应该有一些空行,并在底部展开宏,如:

public: void GetMyVariable(){ return m_MyVariable; };

你可以不用编译就测试宏,这样做很快。

f0brbegy

f0brbegy5#

如果你想看到预处理器生成的扩展代码,那么你可以使用gcc的-E标志来获取它。

$ gcc -E <source code> -o <preprocessed file name>

您可以使用macro将原始源代码替换为扩展代码,并放置您想要放置的任何断点。

4zcjmb1e

4zcjmb1e6#

如果你正在使用Visual Studio来处理使用宏的C或C++项目,那么就使用Resharper for C++(我相信有一个试用版)。它允许你点击一个宏,然后完全展开它,或者分阶段展开它。我们有一些极其复杂的嵌套宏,这是理解它们的唯一方法。

wztqucjr

wztqucjr7#

我说过宏非常复杂吗?我想在调试时只展开一两层,而不是所有的宏(否则它显然是不可读的)...
如果没有太多的宏你不想扩展,那么你可以简单地在你想调试的代码段之前#undef它们。然后如上所述用[Generate Preprocessed File]编译。编译会失败,但是你会在预处理输出中得到一个可用的代码段,并带有正确的扩展。复制粘贴,删除#undef-s并调试。
遗憾的是,处理C风格宏最好的朋友是内联模板和一个好的优化编译器。

iezvtpos

iezvtpos8#

使用内联函数(如果你真的想内联,就强制内联)并坚持使用它!这样会更高效(如果你优化了perf,只有当它带来性能时才内联)和可维护性。使用宏会损失很多:类型检查和安全。
宏并不存在于编译器中,它们只存在于预处理器中。这个宏在不寻找副作用的情况下进行文本替换。所以宏实际上从来没有被调用过,你也不能调试它们。无论你如何编写宏,误用总是可能的。就像这个例子:

#define SQUARE(a) ((a)*(a))

注意( ')可以防止像SQUARE(3+2)这样的替换,但是它们不能防止:

int a = 1;
int b = SQUARE(++a);

有人会期望它是4,但你最终得到的是6,这不是真正的正方形,当它扩展到int b = (++a)*(++a);时,你就不会有内联函数的麻烦了。
注意,内联函数的实现必须在你使用它的地方对编译器是可见的,而且调试对于新手来说也会很奇怪:因为一个内联函数有很多示例,如果你想把执行点移到另一个地方,你会得到一个巨大的方法列表。

qjp7pelc

qjp7pelc9#

是的,你可以。
在Debug文件夹中找到由预处理器生成的预处理文件
因此,如果您的宏是在 * testing. c * 文件中编写的,则预处理文件将称为 * testing. i *
在那里,您可以看到宏是如何展开的。
要调试它,只需将此代码复制粘贴到您的:)

相关问题