我遇到了一个奇怪的问题。我的应用程序的Release
版本似乎运行良好,但最近当我切换到Debug
版本时,我在启动时立即遇到了访问冲突。释放已分配内存块时发生访问冲突。所有这些都发生在静态变量的构造函数中。
我认为Release
版本中的问题并不是因为我在那里定义了NDEBUG
,我相信它会在C运行时禁用断言。
我已经能够缩小范围。如果我在通常的调用之前将以下代码添加到构造函数中,那么我得到相同的错误:
int *temp = new int[3];
delete[] temp;
这让我觉得这个代码块之外的东西导致了这个问题,例如,可能存在C运行时链接方式的问题。但是,我不知道该问题可能是什么,经过一天的问题解决后,我已经不知道接下来会去哪里寻找。
非常感谢任何帮助。我正在使用Visual Studio 2010来编译应用程序并运行Windows 7。
非常感谢!
答案 0 :(得分:2)
在调试模式下,会添加其他检查;因此,程序在发布模式下运行良好但在调试模式下发出访问冲突并不罕见。这并不意味着Release版本没问题;它只表示发布版本运行时发生的某些错误没有被捕获,而是在调试模式下运行时。
在C / C ++中调试损坏的内存问题非常困难,因为错误可以由影响内存的任何其他指令产生。例如,如果在分配的内存中有两个数组相互跟随并且第一个数组溢出,那么它将破坏第二个数组之前放置的标头(每个内存分配都以标头为前缀;此标头用于当取消分配内存时,运算符删除并删除[]。但是,只有当您尝试释放第二个数组时才会发生访问冲突,即使它与第一个数组一起发现代码中存在错误。
当然,您可以在第二个阵列中遇到其他问题。例如,您可以在尝试从中读取时,发现其部分或全部值已损坏。然而,情况并非总是如此,并且在许多情况下,它在读取或写入时可能表现得非常好,并且您可以与第一个数组具有完全相同的良好行为。这并不是因为你不会在某些阵列中读取和写入任何问题,而这些阵列不会超越其边界并破坏其上方(或下方)的内存。有时,问题只会在尝试解除分配数组时出现,否则会出现问题;例如,显示损坏的值。
答案 1 :(得分:0)
我能够通过切掉基本上所有的应用程序代码来生成一个最小的例子。我将InitInstance
函数简化为以下内容:
BOOL CTempApp::InitInstance()
{
int *temp = new int[3] ;
delete[] temp ;
return FALSE ;
}
即使我的所有应用程序代码都被删除,问题仍然存在。在此之后,我在Visual Studio 2010中创建了一个新项目,再次使用我的最小版本替换InitInstance
,然后在链接器选项中添加了原始项目中的所有Additional Dependencies
。通过这种配置,问题得以重现。
接下来,我开始从依赖项列表中删除库。我设法将列表缩减为单个第三方库,尽管被标记为调试版本,但仍导致以下链接器警告:
LINK : warning LNK4098: defaultlib 'msvcrtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
我认为这里发生的事情是供应商已将其调试库与非调试运行时相关联。据推测,当我的应用程序调用{{1}}时,对调用的参数有一些混淆,并且它试图删除我尚未分配的内存部分。
我尝试将以下内容添加到我的delete[]
列表中:
Ignore Specific Default Libraries
建议here 。但问题仍然存在。我认为解决方案是与供应商联系并让他们解决冲突。
再次感谢您的建议。我希望这个答案可以帮助其他人调试类似的问题。