调试断言失败!表达式:_pFirstBlock == pHead

Con*_*ngo 33 c++ visual-studio-2012

我正在调用一个静态链接的.dll,我看到这个错误:

在此输入图像描述

我写了.dll和调用代码.不应该发生此错误.我想知道是否有其他人以前遇到过它?.dll只包含大约10行代码,它只是一个测试.dll来查看dll如何工作.当我从.dll传回一个std :: string时它会爆炸.

我正在使用Visual Studio 2012和C++.

接下来我会尝试什么

来自Debug断言... _pFirstBlock == pHead:

如果在多线程模块中使用单线程库,则会发生此问题.

明天,我将尝试在多线程模式下重新编译Boost静态库(我的.dll设置为多线程静态模式).

接下来我会尝试什么

请参阅在从DLL导出的对象中使用字符串会导致运行时错误:

你需要做两件事之一

  1. 使DLL和使用它的客户端都链接到 CRT 的DLL版本(例如,不静态).
  2. 或者您需要确保不跨DLL边界传递动态分配的内存(例如字符串对象中包含的内存).换句话说,没有返回字符串对象的DLL导出函数.

这似乎与正在发生的事情相匹配,它在我将字符串传回.dll边界的精确点处爆炸.只有在静态模式下链接所有内容时才会出现此问题.现在这是可以解决的.

请参阅在dll边界上传递对STL向量的引用.

接下来我会尝试什么

请参见无法跨DLL传递std :: wstring.

我有一个很好的解决方案,请参阅下面的答案.

Con*_*ngo 38

在这种情况下,问题是我正在std::string向后传递.dll边界.

运行时库配置

  • 如果MSVC Runtime library设置为Multi-threaded Debug DLL (/MDd),那么这没有问题(它工作正常).

  • 如果MSVC Runtime library设置为Multi-threaded Debug (/MTd),则会抛出此错误,可以使用以下说明修复此错误.

内存管理器A中分配的内存并在内存管理器B中释放...

问题是内存是在.dll端分配的,然后在应用程序端释放相同的内存.这意味着内存管理器A正在分配内存,而内存管理器B正在释放生成错误的相同内存.

解决方案是确保传回的所有内存都不在DLL中分配.换句话说,内存总是在应用程序端分配,并在应用程序端释放.

当然,DLL可以在内部分配/释放内存 - 但是它不能分配稍后由应用程序释放的内存.

例子

这将工作:

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

这将有效:

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

但是,这还不够.

在应用程序端,必须预先分配字符串:

std::string text("");
text.reserve(1024);     // Reserves 1024 bytes in the string "text".
Run Code Online (Sandbox Code Playgroud)

在.dll端,必须将文本复制到原始缓冲区中(而不是使用.dll端分配的内存覆盖):

text.assign("hello");
Run Code Online (Sandbox Code Playgroud)

有时,C++仍会坚持分配内存.仔细检查预分配是否仍然如下:

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

另一种方法是使用std::shared_ptr<std::string>,所以即使在.dll中分配了内存,它也会被.dll(而不是应用程序端)释放.

另一种方法是接受char *指示预分配存储量的a 和长度.如果我们要传回的文本长于预分配内存的长度,则返回错误.