从 C# 调试 C++ dll

Debug C++ dll from C#

我简单说一下情况。 我有一个 C# 项目,它使用一些在 C++ 中创建的 DLL。

现在,另外,我还有一个C++项目,前段时间用来创建那个DLL。 现在,我想在 运行 C# 项目期间调试 C++ DLL。

我在我的 C# 项目中启用了 "Enable Unmanaged Code Debugging"。

我开始调试 C# 项目并逐步执行一些功能。 一切似乎都还好。当我到达一个属于 C++ DLL 的函数时, 它询问 C++ 文件的来源,我必须浏览到我的 C++ 项目。 (在我认为它抱怨某些 .pdb 文件之前)。

现在,我也成功地进入了 C++ 函数,但是当我一遍又一遍地进入时,该函数中的一些数据结构似乎没有填充数据,例如,请看下面的截图

你可以看到 blob 数据结构是空的,DataParser 也是如此(它显示它里面有 0 个项目,而在上面的代码中你可以看到有多个项目被添加到它) .

非常感谢您的帮助,这里出了什么问题?以及我可能犯错的地方。我如何调试此 C++ DLL,以便我还可以查看当前分配给其变量的值?

也许我调试这个C++ DLL的方式不对?事实上,C# 项目正在使用一个已经创建的 DLL,而我有这个 C++ 项目,它在不久前被用来创建这个 DLL - 事实上它们是分开的,也许这也与它有关?

PS 在我不得不对 C++ 项目和较低的工具集进行 this 之类的更改之前,因为我使用 VS2012(如果项目是使用 VS2013 创建的,这很奇怪,因为我认为它是旧项目)。该项目还使用了大量手动编写的其他 C++ 类。也许这也是问题所在,不知何故编译器无法检索它们的值和定义?

在像我这样的设置中调试 C++ DLL 文件的一般步骤是什么?

编辑:PPS。我还看到了一些其他有趣的事实。例如,如果我在 DataParser.Add 函数上单击 F11(进入),我不一定会被带到该函数的主体,它会向我显示其他函数的主体(可能与它有某种关系)。

此外,如果我在第一次调用 Request.Add 后按 F10 说,它会跳过多行 Request.Add 行,例如移动到第五行。

EDIT2同样在我进入 C++ 代码之前,它向我显示警告 "the source is different version than the one that was used to create a DLL"。有问题吗?

模块和 PDB

模块 (.dll/.exe) 和调试数据库 (.pdb) 之间有一个 link。 link 是通过两个文件中都存在的时间戳和校验和建立的。 Visual Studio 检查那些的正确性,否则它会抱怨并且根本不会在断点处停止。

虽然 WinDbg 等其他调试器有关闭该功能的命令,但 Visual Studio 没有这样的功能,需要主动操作(例如 Chkmatch)来关闭校验和验证.只要你没用过这样的工具,你的调试符号就没问题。

PDB 和来源

在调试数据库(.pdb)和源代码之间也有一个link。这个link是由文件名和行号建立的。您可以猜到,您的源代码在编译期间不会被修改,因此源代码不包含任何可以验证的校验和或时间戳。

因此,来源可能已更改,行号甚至可能不再大致匹配。行号被破坏的原因有多种。我有 answered a similar question before 并列出了以下行号更改的原因,尽管代码本身没有更改:

  • 代码重新格式化,例如按可见性对方法进行排序,因此移动了完整的方法
  • 代码重新格式化,例如在 80 个字符处打断长行,通常这会向下移动
  • 优化 usings (R#),它删除了 30 行不需要的导入,因此事情进展顺利
  • 插入注释或换行符

如何调试

  1. 如果可以,请恢复该版本的确切源代码。
  2. 完全无源码调试,仅靠PDB信息。这样你可以保留二进制组件,如果这很重要(例如,如果一个错误只能用那个版本重现)
  3. 重建所有模块,使代码再次匹配模块。这样你就丢失了二进制文件,问题可能不会再重现。