高级Visual Studio功夫测试 - 在调试期间从立即窗口调用函数

时间:2010-06-10 04:47:29

标签: visual-studio debugging runtime immediate-window

我看到一些相关的问题已被提出,但它们要么太先进了,要么从头到尾掌握或缺乏循序渐进的指导(大多数人最终都在谈论他们自己的实验结果)。好的,这是一个简单的程序:

#include <stdio.h>
#include <string.h>

int main()
{
    FILE * f;
    char buffer[100];

    memset(buffer, 0, 100);

    fun();

    f = fopen("main.cpp", "r");
    fread(buffer, 1, 99, f);
    printf(buffer);
    fclose(f);

    return 0;
}

它的作用基本上是打印本身(假设文件名为main.cpp)。

问题

如何在不修改源代码的情况下打印另一个文件,比如foobar.txt ?它与通过VS运行它,逐步执行函数并在调用fread()之前劫持FILE指针有关。无需担心通过调用fclose()来泄漏资源。

我尝试了提供

的简单f = fopen("foobar.txt", "r")
CXX0017: Error: symbol "fopen" not found

有什么想法吗?

修改

我在Debugging Mozilla on Windows FAQ意外地发现了解决方案。放入立即窗口的正确命令是

f = {,,MSVCR100D}fopen("foo.txt", "r")

然而,它并没有真正回答这个问题:

  • 我仍然不明白这里发生了什么。
  • 如何系统地找出任何给定方法的{,,MSVCR100D}部分?我知道MSVCR版本在不同系统之间有所变化。我怎么能找到它?
  • 任何人都可以解释大括号的语法,特别是那两个逗号在那里做什么?使用这种语法有更多隐藏的宝石吗?

2 个答案:

答案 0 :(得分:6)

大括号语法是VS Context Operator,它大部分被破坏 - 正如在链接上详细说明的那样(或者至少是一个隐藏的宝石)。它用于VS表达式评估引擎需要在运行时解析函数的任何地方,例如在观察窗口中评估复合表达式,在立即/命令窗口中设置断点或(如您所见)。

它的第三个参数是二进制文件,它包含你想要调用的函数的实现。对于CRT函数,例如fopen,通常等于 -

  

MSVCR [VS版] [D] .dll

(我似乎记得扩展是必要的 - 但可能在VS2010中有所改变)。 “D”表示调试dll版本。 VS版本号被解码为:VS2005 - &gt; 8,VS2008 - &gt; 9,VS2010 - &gt; 10。

另请注意,评估引擎需要注意various other gotchas

答案 1 :(得分:4)

为了补充Ofek的优秀答案,我发现这是一种系统地找出函数调用属于哪个模块的方法。 (即MSVCR100D部分)。

  • 逐步调试调试器,查找要调用的函数的实例。 (在这种情况下,我正在寻找fopen);
  • 找到它后,按F11进入。
  • 右键单击并选择“显示反汇编”
  • 您可以找到当前正在执行的指令的地址。 (如果未显示,请单击“查看选项”以进行切换)
  • 打开模块调试窗口(Alt + Ctrl + U)
  • 查看已加载模块的列表,其中包含覆盖当前指令地址的地址范围。 Bam,你找到了函数的模块名称!

我相信您可以使用此方法查找任何类的模块名称。例如,当您查看大型代码库并且希望在立即窗口中动态调用某些任意类的方法时,这可能很有用。您也可以通过自己调用构造函数来动态创建类的实例。

现在C ++不是母语吗?我们几乎感觉像是在托管的脚本环境中:P