C#项目中的“优化代码”选项如何导致本机代码崩溃?

时间:2012-06-13 21:24:34

标签: c# visual-studio-2010 debugging c++-cli

我有一个Windows Forms应用程序,它使用SQLite文件作为文件格式。这些文件由本机代码创建,该代码通过C ++ / CLI包装器调用,其中包括对托管代码的回调以进行进度/取消更新。这对于32位一直很有用。我试图通过切换到64位来消除我的内存上限,并遇到了一个重大障碍。

当在本机代码中分配或释放内存时,我得到伪确定性崩溃,这让我想到了内存损坏。但它只发生在发布版本中,并且只是没有附加调试器。这是我噩梦的细分:

Config   Bits Optimizations Interop Dbg-symbols Runtime With-debugger Without-debugger
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
Release   64     off          yes      no         /MD    no crash         no crash
Release   64     off          yes      yes        /MD    no crash         no crash
Debug     32     off          no       yes        /MDd   no crash         no crash
Debug     32     off          yes      yes        /MDd   no crash         no crash
Debug     64     off          yes      yes        /MDd   no crash         no crash
Debug     64     on           yes      yes        /MD    no crash         no crash
Debug     64     on           yes      no         /MD    no crash         no crash
Debug     64     off          yes      yes        /MD    no crash         no crash
Debug     64     off          yes      yes        /MDd   no crash         no crash
Debug     64     on           yes      yes        /MDd   no crash         no crash
Debug     64     on           yes      no         /MD    no crash         no crash

“Interop”意味着我正在使用GUI应用程序中的C ++ / CLI包装器来运行本机解析器代码。我有一个用本机C ++编写的命令行驱动程序,它不会在任何配置中崩溃。

基本上调试配置永远不会崩溃,即使本机代码编译完全像发布代码!我比较了响应文件,它们是相同的,除了我为调试配置添加了_NO_DEBUG_HEAP = 1。我怀疑在使用/ MD和定义NDEBUG时无论如何都会产生任何影响。那我该怎么调试这个噩梦?它不觉得我的代码有问题。请不要问一个小的复制品,我不知道如何制作它。但是代码都是开源的,所以如果有人想要重现这个,我会发布一个链接到源代码。

1 个答案:

答案 0 :(得分:0)

Heisenbugs通常由内存踩踏(在托管代码中不会发生)或将内存中的垃圾视为有效数据引起。

我已经找到了多个通常可重复的heisenbugs,这些heisenbugs使用了一个未初始化的变量,可以从另一个例程中拾取堆栈中的任何内容。您的本机代码可能包含这样的错误,当它获得一个值时会起作用,而当它获得另一个值时会爆炸。调试与发布不保证幕后的东西是一样的(毕竟,如果这就是为什么会有这两种配置?)并且你可能在内存中有不同的垃圾。

优化器也可能有这样的效果。

我会尝试一件事:将一个实质性结构压缩到本机代码中第一个例程的局部变量中。做一些事情来防止链接器剥离它。

这会移动一些东西,如果它是内存中的垃圾问题,这应该会改变行为。