我有一个原型类似以下的功能:
void function(std::string str);
该功能被称为在我的主要功能,在加载并使用该DLL另一个程序。
function("some string value here");
当从这个函数返回,我得到堆损坏错误:
Windows已经引发了Program.exe文件断点。
这可能是由于堆,其指示的Program.exe或任何它已加载的DLL的一个错误的损坏。
这也可能是由于用户按下F12键,同时拥有的Program.exe焦点。
输出窗口可以具有更多的诊断信息。
我的代码打转转,我注意到几个怪意见:
1.当传递的字符串的长度不超过11个字符我没有得到任何错误,当我添加更多的字符出现的错误。
2.当改变参数从所述类型std::string
到std::string&
错误消失。 顺便提及的想法来自这里 。
3.我已经注释掉的函数体。 在那里操作无关与产生的异常。
来自4.更改参数类型std::string
到char*
也解决了这个问题。
这可能是造成这个错误? 如何解决这个问题呢?
最有可能的,你看到的崩溃是由于这样的事实,在Windows中的DLL有自己的私有堆。
当你编译你的函数,编译器生成一些代码std::string
的析构函数,以清理其参数。 此代码释放的DLL堆上分配的内存。 但是,应用程序EXE也产生它自己的代码std::string
的构造函数,分配上的程序堆的代码。 当您分配一个堆和自由,另一方面,不确定的行为发生,而你崩溃。
至于为什么小弦不触发错误-许多std::string
实现内联小弦成结构本身,以避免堆的开销。 当你的字符串是足够小,以适应,不存在存储器分配需要发生,因此正好出现工作...只要你使用相同的STL版本都EXE和DLL,以及内联的门槛永远不会改变。
为了避免这个问题,不按值传递对象的DLL(除非它们是POD对象 ),并以不同的DLL或EXE比其创建不释放一个对象,避免周围路过STL或C ++库对象为好,因为它们的实现方式可以不同版本的C ++编译器的不同。 通POD对象或C原始类型如const char *
代替。
当导出DLL函数,这是最好的,如果他们只接受完整的数据类型,即int或指针(不知道float和double)。
当你需要传递一个字符串,将它作为const char *
,当你需要的DLL函数返回一个字符串,一个传递给DLL char *
指针指向一个预先分配的缓冲区,该DLL会写的字符串。
从来不会使用的DLL自己的功能之外DLL分配的内存,也不会被认为有自己的构造函数/析构函数值结构传递。
也许你已经与C运行时的静态版本链接,这是从来没有创建与C运行时的静态版本链接的DLL是个好主意。 这可能会导致程序中的许多问题,例如你的EXE从它与它连接的静态C运行时的私有堆中分配内存,然后在你的DLL要删除堆,并创建一个新的堆(因为你要添加一些数据输入的字符串,它需要扩大其缓冲),所以它会导致错误。 这个简单的方法是你的程序(EXE和DLL)的所有部分与C运行时的DLL版本链接,所以他们从MSVCRTXX.dll都共享同一个堆