我今天遇到了这个错误,原因是我在调用FreeLibrary()
后使用了一个字符串从我的DLL中分配。
这是复制崩溃的简单示例。这是在DLL中:
void dllFunc(char **output)
{
*output = strdup("Hello"); // strdup uses malloc
}
这是在加载DLL的EXE中:
void exeFunc()
{
char *output;
dllFunc(&output);
std::string s1 = output; // This succeeds.
FreeLibrary(dll);
std::string s2 = output; // This crashes with access violation.
}
我阅读了FreeLibrary()
的文档,但是在调用后,我找不到任何关于内存变得无效的内容。
修改
我刚刚意识到我在使用VS2010工具链进行EXE时一直使用VS2008工具链(我使用VS2010作为IDE的两者,但你可以从项目设置中选择工具链)。为DLL设置工具链到VS2010也删除了崩溃。
答案 0 :(得分:6)
如果选择与MSVCRT(C运行时)库的静态链接,您将获得您描述的行为。如果您的EXE和DLL动态链接到MSVCRT DLL,但使用的是不同版本,也会发生同样的情况。或者如果它们匹配相同的版本,但是一个使用DEBUG而另一个使用RETAIL。换句话说,内存只能与用于进行分配的MSVCRTxxx.dll的生命周期一样好。我刚刚看到你对你的问题的更新 - 是的,混合和匹配VS 2008和2010之间的CRT是崩溃的确切原因。
如果您的DLL和EXE都动态链接到MSVCRT DLL的相同版本,那么您可以共享内存堆,从而避免出现问题。
标准做法是:如果导出的DLL函数返回需要稍后“释放”或“释放”的任何内容,那么标准做法是提供从DLL导出的附加函数来处理取消分配。 / p>
您可以从代码生成页面为项目中的C / C ++项目设置配置EXE和DLL的C运行时链接。
图片来源:http://imgur.com/uld4KYF.png
答案 1 :(得分:5)
这是因为每个Dll创建自己的内存堆(malloc
及其C朋友和new
将在内部使用,通常通过HeapAlloc
),当Dll是自由,它的堆也是如此。
有关更多Dll内存警告,请参阅this MSDN article。除非您使用在所有二进制文件中共享的自定义内存分配器,否则您需要在创建它的模块中保留动态分配的内存(除非您可以100%保证该对象不会超过其创建者)。