C# / C++应用程序在从Windows运行时崩溃,但不是从Visual Studio

本文关键字:Studio Visual 崩溃 运行时 C++ 应用程序 Windows | 更新日期: 2023-09-27 18:36:37

我正在开发一个C#应用程序,它调用一个非托管(C++)dll。 我发现某个用户操作在从 Windows 资源管理器运行时始终导致应用程序崩溃。 但是,从 Visual Studio 调试器启动时,不会发生崩溃。 因此,我无法在崩溃时单步进入代码并准确调试正在发生的事情。

什么可能导致二进制文件在从资源管理器运行时崩溃,而不是从Visual Studio运行? 请注意,我使用的是发布版本;调试版本在Visual Studio资源管理器中都不会崩溃。

(如果相关,我可以说崩溃与在C++ DLL中操作malloc分配的数组有关。 我通过煞费苦心地注释掉代码块,重建,从Windows运行以及检查是否发生崩溃来追踪它。 但是,我已经到了这样一个地步,即在无法正确中断调试器的情况下,很难继续)。

我只是对能够在Visual Studio中重现崩溃感兴趣。

C# / C++应用程序在从Windows运行时崩溃,但不是从Visual Studio

当程序在调试中工作但在发布中崩溃时,问题通常是缓冲区溢出,因此您应该查找不正确的缓冲区长度变量之类的内容。

关于调试

时为什么它不会崩溃,这里有一篇关于调试器副作用的小文章。如您所读,当调试器启动程序时,堆可以具有不同的行为。缓冲区溢出经常发生在堆上,您说它可能发生在 malloc-ed 缓冲区中,所以这就是原因。

现在,要使程序在调试时崩溃,唯一的方法可能是在启动后附加。如果在 DLL 项目中设置断点不起作用,请尝试改为使用 DLL 项目启动调试,并将可执行文件指定为 DLL 主机。如果你不能命中这样的断点,那么,你总是可以在汇编代码中设置断点,这应该总是有效的,但并不实用。可以使用 MSVC 上的 __debugbreak() 添加已编译的程序集断点。

请注意,即使在附加时,仍可能出现差异,调试器将始终略微更改目标行为。尽管只有未定义的行为应该改变。

编辑:我错过了,但文章说您可以通过设置环境变量_NO_DEBUG_HEAP = 1来禁用调试堆。这可能是调试问题的最简单解决方案(如果有效)。