DLL内存分配相关问题














跨dll使用template/STL需要注意的问题

dll:

extern "C"
{
 __declspec(dllexport) void PrintVector(const vector<int> v)
 {
  copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
 }
}

exe:

typedef void (* FUNC)(const vector<int>);

int main()
{
 HMODULE hModule = LoadLibrary("VectorDll.dll");
 if (hModule)
 {
  FUNC fun = (FUNC)GetProcAddress(hModule, "PrintVector");
  vector<int> v(10, 1);
  fun(v);
 }
 return 0;
}

上面代码存在严重的问题,运行时会崩溃:


在windows核心编程中明确的说了在dll中如果申请了内存空间,就一定要在dll中释放这块内存空间。

在exe和dll都静态链接到C/C++运行时库的时候,exe和dll都有各自的堆(heap)空间,所以各自申请的内存需要各自释放。

上面代码将参数改成 const vector<int> & 就可以正常运行。

但是如果exe中的vector版本和dll中vector的版本不同,问题又会出现,并且这些是未知的问题。

所以在dll函数接口中尽量使用基本数据类型。

关于exe和dll内存分配:

http://www.codeguru.com/forum/showthread.php?t=229394

http://www.gamedev.net/community/forums/topic.asp?topic_id=289896

http://blog.youkuaiyun.com/dotphoenix/archive/2009/07/14/4348686.aspx

http://blog.sina.com.cn/s/blog_60d705b10100g4ou.html

http://hi.baidu.com/honey%BC%A6/blog/item/8780d1f918976ed5b58f310f.html

关于dll和template/STL:

http://www.hellocpp.net/Articles/Article/714.aspx




DLL分配的内存如何在EXE里面释放

总结下面几个要点:

1. 保证内存分配和清除的统一性:如果一个DLL提供一个能够分配内存的函数,那么这个DLL同时应该提供一个函数释放这些内存。数据的创建和清除应该在同一个层次上。

曾经遇到过这样的例子:在dll中分配了一块内存,通过PostMessage将其地址传给应用。然后应用去释放它,结果总是报异常。

2.如果exe用 MFC Appwizard方式生成, dll用win32方式生成,则运行时会出现错误。进一步用单步跟踪,发现mfc方式和win32方式下的new操作符是用不同方式实现的,源程序分别在VC目录的文件 Afxmem.cpp和new.cpp中。有兴趣的话可以自已跟踪一下。

因为dll输出函数后,并不知道是哪一个模拟调用它,因此new和delete配对时最好在一个文件中,这样可以保证一致性。

3. 问题主要在于DLL和EXE主程序中分配内存的堆不一样,你可以不用new和delete,而是用

1) ::HeapAlloc(::GetProcessHeap(),...)和::HeapFree(::GetProcessHeap(),...)

2) ::GlobalAlloc()和::GlobalFree()

这两对API,这样无论在DLL中还是在主程序中都是在进程默认堆中分配,就不会出错了。

4. 还有一个办法,就是把dll的Settings的C/C++选项卡的Code Generation的Use Run-time liberary改成Debug Multithreaded DLL,在Release版本中改成Multithreaded DLL,就可以直接使用new和delete了。不过MFC就不能用Shared模式了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值