【问题标题】:How does a .NET program behave differently when run with and without debugging in Visual Studio?在 Visual Studio 中调试和不调试时,.NET 程序的行为有何不同?
【发布时间】:2011-01-20 03:52:41
【问题描述】:

在关闭我的 .NET 应用程序时,我在 DBEXPSDA40.DLL(Dev Art MS SQL Server dbexpress 驱动程序)中遇到访问冲突。我的应用程序 (VB.NET) 调用一个 Delphi 编写的 COM Server,它使用 dbexpress 连接到 SQL Server。

如果我做同样的事情,但我的主机应用程序是本机 Delphi 应用程序或 Excel VBA,那么我看不到 A/V。如果我在带有调试功能的 VS IDE 中运行 VB.NET 应用程序,我也看不到它。

我已经在 dbexpress 单元中将 A/V 跟踪到一个 finalization 子句,该子句负责关闭驱动程序(在本例中是两个,一个用于 SQL Server,另一个用于 SQL Server Compact)

如果我能弄清楚在 .NET 环境中进行调试和不进行调试之间的区别,我或许可以知道在哪里进一步研究。

【问题讨论】:

  • AV可以隐藏,但不代表不存在。怎么查?
  • 我可以追踪(在Delphi中)通过终结,并且驱动程序的句柄(指针)在它工作时有效,而不是在它不工作时无效

标签: .net delphi com dbexpress


【解决方案1】:

您的区别在于内存布局。

有很多微妙的因素会影响这个过程。一方面,在调试器下,JIT 生成的代码略有不同(以适应调试器)。根据您的调试器设置,Visual Studio 还可能在您的进程中注入一些其他代码(例如 .vshost.exe)。调试器还可以影响时间,进而可能会暴露竞争条件和/或更改内存分配方式。

长话短说,在应用程序关闭时,您最终会得到 [轻微或显着] 不同的内存布局。显然,不同的主机应用程序也是如此。

但这只是故事的一方面。另一方面是dbexpress中存在错误。或者,其他一些模块可能会导致 dbexpress 数据中的内存损坏。无论哪种方式,dbexpress 最终都会访问一些随机地址。

并且该地址在一种情况下恰好位于未分配的内存页面上,但在其他情况下恰好位于已分配的内存页面上(因为内存布局不同,记得吗?)。而在后一种情况下,dbexpress 只是从内存中读取值,对其进行处理,显然对结果感到满意,然后优雅地退出。

这(以及无法追踪的竞争条件)是未成熟编写的非托管代码的一个非常常见的问题(我的经验表明,这通常是涉及 Delphi 的情况)。

解决方案?改变条件。 您可以在不同的机器上尝试。或者在同一台机器上,但负载很重。或者加载更多模块。或者不要加载您通常使用的某些模块。玩它。

话虽如此,您真正的个人永远不会那样做。它只是变成了大海捞针,永无止境,令人筋疲力尽的冒险。此外,您很有可能在其他地方获得 AV(但原因相同)。

另一个(更好的)选项是调试打印。也就是说,如果你有 dbexpress 的源代码(对不起,我不熟悉它)。

否则,我将首先对 Delphi 组件进行非常仔细的代码审查。并且可能还在那里调试打印。

祝你好运。

【讨论】:

    【解决方案2】:

    主机应用程序可能对您隐藏了异常。关机错误是最难的。添加一些日志来查看调试器分离时是否发生异常。

    【讨论】:

    • 我很确定主机应用程序没有隐藏错误,我可以在 Delphi 中调试自动化 dll,并且当我启动主机进行调试时,有问题的行是可以的,但当我启动时不是它在 VS 之外。
    猜你喜欢
    • 2023-01-29
    • 1970-01-01
    • 2021-08-17
    • 2017-10-04
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2014-05-31
    相关资源
    最近更新 更多