很多书上都说“谁分配,谁释放”,除了从设计哲学上保持代码的一致性外,我们从一个 .dll 分配,另一个 .dll 释放,其实也是有问题的。下面就来看看问题在哪。
下面是 vs2005 crt 中一个文件的节选,从中可以看到,malloc/free 其实就是调用了 HeapCreate/Alloc/Free 等 win32 API。注意:smalheap.c 文件只是起注释作用,实际的 malloc/free 的实现,参见 heapinit.c / malloc.c / free.c 等文件。
---------------------------------------- smalheap.c ------------------------------------------
HANDLE _crtheap=NULL;
/*
* Primary heap routines (Initialization, termination, malloc and free).
*/
void __cdecl free (
void * pblock
)
{
if ( pblock == NULL )
return;
HeapFree(_crtheap, 0, pblock);
}
int __cdecl _heap_init (
int mtflag
)
{
if ( (_crtheap = HeapCreate( mtflag ? 0 : HEAP_NO_SERIALIZE,
BYTES_PER_PAGE, 0 )) == NULL )
return 0;
return 1;
}
void __cdecl _heap_term (
void
)
{
HeapDestroy( _crtheap );
_crtheap=NULL;
}
void * __cdecl _nh_malloc (
size_t size,
int nhFlag
)
{
void * retp;
for (;;) {
retp = HeapAlloc( _crtheap, 0, size );
/*
* if successful allocation, return pointer to memory
* if new handling turned off altogether, return NULL
*/
if (retp || nhFlag == 0)
return retp;
/* call installed new handler */
if (!_callnewh(size))
return NULL;
/* new handler was successful -- try to allocate again */
}
}
void * __cdecl malloc (
size_t size
)
{
return _nh_malloc( size, _newmode );
}
------------------------------------- smalheap.c end ------------------------------------------
好了,我们来看看问题出在哪。如果都用 /MD dynamic-link crt,其实你用几个 DLL 都是没有问题的,相互之间混用 malloc/free 也不会挂。但 /MT 问题就来了:
a.exe + b.dll (两者都是 /MT static-link crt)
p = malloc(); // b.dll
free(p); // a.exe
实际上相当于:
heap_b_dll = HeapCreate();
p = HeapAlloc(heap_b_dll);
HeapFree(heap_a_exe, p);
挂不挂,只是操作系统的问题,经测试。XP 没挂,而且 HeapFree 居然没有报错,而 Vista 就玩完了~
XP 虽然不报错,但肯定也是有问题的,咔咔。
结论很明了,还是书上说的“哪里分配,哪里释放”,使用 /MT dll 的同学,记得把某个类的 new/delete 都放到一个 DLL 里面管起来,就米问题了。另一个解法就是全部都用 /MT lib,所有东西全部打包到一个 .exe 里面啦。
当然,全部用 /MD 肯定是可以的。
下面有篇抛砖引玉的文字,不错的说,不过解决问题还要靠自己查代码:
http://topic.csdn.net/u/20090104/09/f6801fcd-32c1-4e4f-b4c7-81fd6d27c82d.html
参考资料:
链接时如何选择C Run-Time(CRT) library, http://www.cppblog.com/aurain/archive/2008/04/23/47911.html
DLLs in Visual C++, http://msdn.microsoft.com/en-us/library/1ez7dh12
crt0.c/crtexe.c/crtdll.c/dllcrt0.c, http://www.cppblog.com/Violetrays/archive/2010/12/01/134077.html
评论