【发布时间】:2012-06-13 21:24:34
【问题描述】:
我有一个使用 SQLite 文件作为文件格式的 Windows 窗体应用程序。这些文件由通过 C++/CLI 包装器调用的本机代码创建,其中包括对托管代码的回调以进行进度/取消更新。这对于 32 位非常有效。我正试图通过切换到 64 位来消除我的内存上限,但遇到了一个重大障碍。
当在本机代码中分配或取消分配内存时,我会遇到伪确定性崩溃,这让我想到了内存损坏。但它只发生在发布构建期间,并且仅在没有附加调试器的情况下发生。以下是我噩梦的细分:
配置位 优化 互操作 Dbg-symbols 运行时 带调试器 不带调试器 Release 32 on no no / MD no crash no crash Release 64 on yes no /MD no crash no crash Release 32 on yes no /MD no crash no crash Release 64 on yes no /MD no crash crash Release 64 on yes yes /MD no crash crash 释放 64 关 是 否 /MD 不崩溃 不崩溃 释放 64 关 是 是 /MD 不崩溃 不崩溃 Debug 32 off no yes /MDd no crash no crash 调试 32 关闭 是 是 /MDd 没有崩溃 没有崩溃 调试 64 关闭 是 是 /MDd 没有崩溃 没有崩溃 调试 64 on yes yes /MD no crash no crash 调试 64 on yes no /MD no crash no crash 调试 64 关 是 是 /MD 不崩溃 不崩溃 调试 64 关闭 是 是 /MDd 没有崩溃 没有崩溃 Debug 64 on yes yes /MDd no crash no crash 调试 64 on yes no /MD no crash no crash“互操作”意味着我正在使用 GUI 应用程序中的 C++/CLI 包装器来运行本机解析器代码。我有一个用本机 C++ 编写的命令行驱动程序,在任何配置中都不会崩溃。
基本上调试配置永远不会崩溃,即使本机代码完全像发布代码一样编译!我比较了响应文件,它们是相同的,除了我为调试配置添加了 _NO_DEBUG_HEAP=1 。我怀疑在使用 /MD 和定义 NDEBUG 时会产生任何影响。那么我该如何调试这个噩梦呢?感觉这不是我的代码的问题。请不要要求一个小的复制品,我不知道如何制作它。但是代码都是开源的,所以如果有人想尝试复制它,我会发布一个指向源代码的链接。
【问题讨论】:
-
添加
Trace::WriteLine以将崩溃隔离到特定位置。一旦你知道了位置,你就会找出原因。 -
@RomanR.:我如何在本机代码中添加它?我使用日志记录将崩溃隔离到代码的某些部分;这就是我知道它可能与分配或释放内存有关的方式。清除 vector
> 时,一个配置崩溃了,但这实际上不应该释放任何内存,它应该只是减少了所有 ptr 的引用计数(它们都保存在其他地方)。我希望这很容易。 :( -
更新:我发现可以通过关闭 C# 项目中的“优化代码”来避免崩溃(这就是为什么带有本机优化的调试配置可以正常工作的原因)。这到底怎么会导致本机代码崩溃?!
-
这听起来像是原生端的未初始化堆栈变量。禁用优化时,由 .NET 端初始化的堆栈部分可能与启用时不同。
-
另外,检查是否可能需要pinning。
标签: c# visual-studio-2010 debugging c++-cli