6

我看到有人问了一些相关的问题,但它们要么太先进,我无法掌握,要么缺乏从头到尾的分步指南(其中大多数最终都是内部人士谈论他们自己的实验结果)。好的,给定这个简单的程序:

#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 版本因系统而异。我怎样才能知道呢?
  • 谁能解释一下大括号语法,特别是那两个逗号在那里做什么?使用这种语法是否有更多隐藏的宝石?
4

2 回答 2

7

花括号语法是 VS Context Operator,它大部分都被破坏了 - 正如链接中所阐述的那样(或者至少,几乎没有隐藏的宝石)。它用于 VS 表达式评估引擎需要在运行时解析函数的任何地方,例如在监视窗口中评估复合表达式、设置断点或(如您所见)在即时/命令窗口中。

它的第三个参数是二进制文件,其中包括您希望调用的函数的实现。对于诸如 fopen 之类的 CRT 函数,这通常相当于 -

MSVCR[VS 版本][D].dll

(我似乎记得需要扩展 - 但可能在 VS2010 中发生了变化)。“D”表示调试 dll 版本。VS版本号解码为:VS2005 -> 8, VS2008 -> 9, VS2010 -> 10。

另请注意,评估引擎还有其他各种需要注意的问题。

于 2010-06-13T12:50:49.760 回答
4

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

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

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

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

于 2010-06-13T14:37:34.623 回答