C运行时库问题MD/MDd
我们有一个C库,我们想分发,连同C示例代码 当然,该库是在发布模式下构建的。 示例代码项目使用cmake,因此可以轻松地在Linux和Windows上运行。 在Linux(调试和发布)和Windows(发布)上,我们都没有问题。 但是,在Windows(调试)上,我们在离开main时遇到一个问题:程序触发断言:C运行时库问题MD/MDd,c,windows,visual-studio,runtime-error,C,Windows,Visual Studio,Runtime Error,我们有一个C库,我们想分发,连同C示例代码 当然,该库是在发布模式下构建的。 示例代码项目使用cmake,因此可以轻松地在Linux和Windows上运行。 在Linux(调试和发布)和Windows(发布)上,我们都没有问题。 但是,在Windows(调试)上,我们在离开main时遇到一个问题:程序触发断言: Invalid address specified to RtlValidateHeap Expression: _CrtIsValidHeapPointer(block) 然后,在继
Invalid address specified to RtlValidateHeap
Expression: _CrtIsValidHeapPointer(block)
然后,在继续该过程时,会引发以下异常:
Unhandled exception at [...] (ntdll.dll)
0xC000000D STATUS_INVALID_PARAMETER
由于这似乎与运行库有关,我们尝试将其从MDd(多线程dll调试)更改为MD(多线程dll)[],从而解决了问题。
然而,这似乎是一种解决方法,而不是修复方法:发行版库(使用MD构建)应该可以在使用MDd的调试程序中使用,对吗
据我们所知,只有在调用者中进行分配,而在被调用者中进行解除分配时,才会出现运行库中的冲突,反之亦然。
因此,我们跟踪了所有分配情况,以检查它们,一切似乎都正常。
我们在Linux(Valgrind)和Windows(CrtDbg)中对示例代码进行了泄漏检测,但他们没有发现任何泄漏,一切似乎都很好
期望使用MD构建的发布库在MDd程序中运行是正确的吗?
如果不是,这似乎很奇怪:库总是在发行版中分发,但在开发过程中用于调试解决方案。。。
如果是,是什么导致问题?听起来更像是堆损坏而不是泄漏。这意味着有人正在覆盖堆(通过其分配的内存)。找到它可能是痛苦的,但是 首先,检查示例代码。将它剥离到最低限度的“hello world”,然后构建它,直到它再次发生。然后检查示例代码。如果不是示例代码,请检查调用了哪些库函数,并检查代码 作为帮助,您可以使用MS heap check函数。将它们放置在函数入口和函数出口处,或者维护您定期检查的全局版本。以下是一个例子:
#include <crtdbg.h>
void example(void)
{
_CrtMemState memStateStart, memStateEnd, memStateDelta;
// Make a checkpoint of the heap's state so we can later check the heap is still OK
_CrtMemCheckpoint( &memStateStart );
//
// do your things
//
// Check the heap
_CrtMemCheckpoint( &memStateEnd );
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_WNDW );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_WNDW );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_WNDW );
if (_CrtMemDifference( &memStateDelta, &memStateStart, &memStateEnd ))
_CrtMemDumpStatistics( &memStateDelta );
_CrtDumpMemoryLeaks();
}
#包括
void示例(void)
{
_CrtMemState memStateStart、memStateEnd、memStateDelta;
//为堆的状态设置一个检查点,以便稍后检查堆是否仍然正常
_CrtMemCheckpoint(&memStateStart);
//
//做事
//
//检查堆
_CrtMemCheckpoint(&memStateEnd);
_CRT报告模式(CRT警告模式、CRTDBG模式、WNDW模式);
_CRT报告模式(CRT错误,CRTDBG模式WNDW);
_CRT报告模式(CRT断言、CRTDBG模式、WNDW);
if(_CrtMemDifference(&memstatedta,&memStateStart,&memstatedend))
_CrtMemDumpStatistics(&memstatedta);
_CrtDumpMemoryLeaks();
}
什么是MD和MDd?无论如何,这听起来更像是堆损坏而不是泄漏。这意味着有人正在覆盖堆(通过其分配的内存)。@PaulOgilvie-我认为MD
&MDd
已经定义,但这在问题中并不清楚。@PaulOgilvie无论如何,这听起来更像是堆损坏而不是泄漏。的确Microsoft的调试库可以在free()
上覆盖内存,并在分配时用非零值填充内存。调试库出现问题而非非非调试运行时出现问题是程序损坏内存的迹象。您可能还希望尝试-fsanize=undefined
查找Linux GCC的未定义行为。或者最后,它可能像用来寻址大于4G的数组的long int
索引一样狡猾,它可以在Linux中工作,因为long int
是什么,并且在Windows中处于释放模式,因为溢出被忽略…一个字符*在库中以静态函数分配,但从未释放。因此,它是由被调用方分配的,默认情况下在退出时由调用方取消分配,引发运行时库冲突,注释代码并通过二分法继续进行,这样我们就可以找到它,在修复之后,问题就消失了。谢谢大家!