4

在关闭我的 .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 环境中进行调试和不进行调试之间的区别,我或许可以知道在哪里进一步研究。

4

2 回答 2

1

您的区别在于内存布局。

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

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

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

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

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

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

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

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

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

祝你好运。

于 2010-03-07T04:42:27.910 回答
0

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

于 2010-02-23T20:37:29.297 回答