Debug Assertion Failed! Expression: _pFirstBlock == pHead

来源:互联网 发布:淘宝店铺排行榜在哪看 编辑:程序博客网 时间:2024/05/16 09:31

In this case, the problem is that I was passing a std::string back across a .dll boundary.

If the MSVC Runtime library is set to Multi-threaded Debug DLL (/MDd), then this is no problem (it works fine).

If the MSVC Runtime library is set to Multi-threaded Debug (/MTd), then it will throw this error, which can be fixed with the following instructions.

The problem is that memory is allocated on the .dll side, then that same memory is freed on the application side. This means that memory manager A is allocating memory, and memory manager B is releasing that same memory, which generates errors.

The solution is to make sure that all memory passed back is not allocated in the DLL. In other words, the memory is always allocated on the application side, and freed on the application side.

Of course, the DLL can allocate/free memory internally - but it can't allocate memory that is later freed by the application.

This will not work:

// Memory is allocated on the .dll side, and freed on the app side, which throws error.DLL std::string GetString(); 

This will work:

// Memory is allocated/freed on the application side, and never allocated in the .dll.DLL int GetString(std::string& text); 

However, this is not quite enough.

On the application side, the string has to be pre-allocated:

std::string text("");text.reserve(1024);     // Reserves 1024 bytes in the string "text".

On the .dll side, the text must be copied into the original buffer (rather than overwritten with memory that is allocated on the .dll side):

text.assign("hello");

Sometimes, C++ will insist on allocating memory anyway. Double check that the pre-allocation is still the same as it was:

if (text.capacity < 1024){   cout << "Memory was allocated on the .dll side. This will eventually throw an error.";}

Another way that works is to use std::shared_ptr<std::string>, so even though memory is allocated in the .dll, it is released by the .dll (rather than the application side).

Yet another way is to accept a char * and a length which indicates the amount of pre-allocated memory. If the text that we want to pass back is longer than the length of pre-allocated memory, return an error.

以上原文转自:http://stackoverflow.com/questions/18882760/debug-assertion-failed-expression-pfirstblock-phead

翻译:这种情况是由于跨越.dll传递std::string造成的。

如果MSVC Runtime library设定为Multi-threaded Debug DLL (/MDd),这个问题不会出现。

如果MSVC Runtime library设定为Multi-threaded Debug (/MTd),则会出现这个问题。

遵循以下步骤可以修复这个问题。

问题出在内存在.dll一边被开辟,而却在application一边却被释放。这意味着A开辟了内存,而B却要释放A开辟的内存,这样就产生了错误。

DLL可以在它内部开辟/释放内存,但是它不可以开辟一个稍后会被application释放的内存空间。

这个不可以:

// Memory is allocated on the .dll side, and freed on the app side, which throws error.// 内存在.dll中开辟,在application中释放,报错。DLL std::string GetString(); 
这个可以:

// Memory is allocated/freed on the application side, and never allocated in the .dll.// 内存在application中开辟和释放,没有在.dll中开辟。DLL int GetString(std::string& text); 
然而,还不够好。

在application一边,字符串应该被预创建。

std::string text("");text.reserve(1024);     // Reserves 1024 bytes in the string "text".
在.dll一边,文本应该被拷贝到原始缓存中(而不是在.dll中复写内存)

text.assign("hello");
有的时候,C++会坚持去开辟内存,因此需要做双检查。

if (text.capacity < 1024){   cout << "Memory was allocated on the .dll side. This will eventually throw an error.";}
另外一个解决方案是使用: std::shared_ptr<std::string>,这样的话内存会在.dll中创建和释放。

还有一个方法是使用 char *,并指明它预开辟空间的大小。如果我们发现传回的内存长度和我们预开辟的大小不一样,那么我们可以返回一个错误。

重要:

我把MSVC Runtime library设定为Multi-threaded Debug DLL (/MDd),问题就解决了。

另外一个讲到这个问题的博客:http://blog.csdn.net/giantpoplar/article/details/47295877



0 0
原创粉丝点击