EXE中释放DLL中分配的内存
2012-09-06 17:17
253 查看
在DLL中分配的内存,如果到其调用者中释放,可能会出现CRASH的情况,其原因在于:
在DLL中的Code Generation如果是采用了MT(静态加载LIBCRTD.LIB)在该库中维护了一个allocator的对象对内存分配进行管理,当EXE中调用free等函数对内存进行释放时,他自己也维护了一个allocator对象(这个对象与DLL中得对象不是同一个对象),所以在free时找不到已经分配的内存,会crash.
在DLL中的Code Generation如果是采用了MD(动态加载MSVCRTD.DLL),那么allocator对象维护在MSVCRTD.dll中,当在EXE中调用时,如果也采用MD,那么他也是使用MSVCRTD中维护的对象,所以在调用free时不会crash.
参考:
Allocating and freeing memory across module boundaries
I'm sure it's been drilled into your head by now that you have to free memory with the same allocator that allocated it.
But this rule goes deeper.
If you have a function that allocates and returns some data, the caller must know how to free that memory. You have a variety of ways of accomplishing this. One is to state explicitly how the memory should be freed. For example, the
states that you should use the
And all memory returned across COM interface boundaries must be allocated and freed with the COM task allocator.
Note, however, that if you decide that a block of memory should be freed with the C runtime, such as with
you have a new problem: Which runtime?
If you choose to link with the static runtime library, then your module has its own private copy of the C/C++ runtime. When your module calls
freed by your module calling
other module which is not the same as yours. Indeed, even if you choose to link with the DLL version of the C/C++ runtime library, you still have to agree which version of the C/C++ runtime to use. If your DLL uses
allocate memory, then anybody who wants to free that memory must also use
If you're paying close attention, you might spot a looming problem. Requiring all your clients to use a particular version of the C/C++ runtime might seem reasonable if you control all of the clients and are willing to recompile all of them each
time the compiler changes. But in real life, people often don't want to take that risk. "If it ain't broke, don't fix it." Switching to a new compiler risks exposing a subtle bug, say, forgetting to declare a variable as volatile or inadvertently relying on
temporaries having a particular lifetime.
In practice, you may wish to convert only part of your program to a new compiler while leaving old modules alone. (For example, you may want to take advantage of new language features such as templates, which are available only in the new compiler.)
But if you do that, then you lose the ability to free memory that was allocated by the old DLL, since that DLL expects you to use
The solution to this requires planning ahead. One option is to use a fixed external allocator such as
These are allocators that are universally available and don't depend on which version of the compiler you're using.
Another option is to wrap your preferred allocator inside exported functions that manage the allocation. This is the mechanism used by the
allocates memory and returns it through the
allocation method is isolated from the caller. Internally, the
It doesn't matter; as long as
Although I personally prefer using a fixed external allocator, many people find it more convenient to use the wrapper technique. That way, they can use their favorite allocator throughout their module. Either way works. The point is that when memory
leaves your DLL, the code you gave the memory to must know how to free it, even if it's using a different compiler from the one that was used to build your DLL.
在DLL中的Code Generation如果是采用了MT(静态加载LIBCRTD.LIB)在该库中维护了一个allocator的对象对内存分配进行管理,当EXE中调用free等函数对内存进行释放时,他自己也维护了一个allocator对象(这个对象与DLL中得对象不是同一个对象),所以在free时找不到已经分配的内存,会crash.
在DLL中的Code Generation如果是采用了MD(动态加载MSVCRTD.DLL),那么allocator对象维护在MSVCRTD.dll中,当在EXE中调用时,如果也采用MD,那么他也是使用MSVCRTD中维护的对象,所以在调用free时不会crash.
参考:
Allocating and freeing memory across module boundaries
I'm sure it's been drilled into your head by now that you have to free memory with the same allocator that allocated it.
LocalAllocmatches
LocalFree,
GlobalAllocmatches
GlobalFree,
new[]matches
delete[].
But this rule goes deeper.
If you have a function that allocates and returns some data, the caller must know how to free that memory. You have a variety of ways of accomplishing this. One is to state explicitly how the memory should be freed. For example, the
FormatMessagedocumentation explicitly
states that you should use the
LocalFreefunction to free the buffer that is allocated if you pass the
FORMAT_MESSAGE_ALLOCATE_BUFFERflag. All
BSTRs must be freed with
SysFreeString.
And all memory returned across COM interface boundaries must be allocated and freed with the COM task allocator.
Note, however, that if you decide that a block of memory should be freed with the C runtime, such as with
free, or with the C++ runtime via
deleteor
delete[],
you have a new problem: Which runtime?
If you choose to link with the static runtime library, then your module has its own private copy of the C/C++ runtime. When your module calls
newor
malloc, the memory can only be
freed by your module calling
deleteor
free. If another module calls
deleteor
free, that will use the C/C++ runtime of that
other module which is not the same as yours. Indeed, even if you choose to link with the DLL version of the C/C++ runtime library, you still have to agree which version of the C/C++ runtime to use. If your DLL uses
MSVCRT20.DLLto
allocate memory, then anybody who wants to free that memory must also use
MSVCRT20.DLL.
If you're paying close attention, you might spot a looming problem. Requiring all your clients to use a particular version of the C/C++ runtime might seem reasonable if you control all of the clients and are willing to recompile all of them each
time the compiler changes. But in real life, people often don't want to take that risk. "If it ain't broke, don't fix it." Switching to a new compiler risks exposing a subtle bug, say, forgetting to declare a variable as volatile or inadvertently relying on
temporaries having a particular lifetime.
In practice, you may wish to convert only part of your program to a new compiler while leaving old modules alone. (For example, you may want to take advantage of new language features such as templates, which are available only in the new compiler.)
But if you do that, then you lose the ability to free memory that was allocated by the old DLL, since that DLL expects you to use
MSVCRT20.DLL, whereas the new compiler uses
MSVCR71.DLL.
The solution to this requires planning ahead. One option is to use a fixed external allocator such as
LocalAllocor
CoTaskMemAlloc.
These are allocators that are universally available and don't depend on which version of the compiler you're using.
Another option is to wrap your preferred allocator inside exported functions that manage the allocation. This is the mechanism used by the
NetApifamily of functions. For example, the
NetGroupEnumfunction
allocates memory and returns it through the
bufptrparameter. When the caller is finished with the memory, it frees it with the
NetApiBufferFreefunction. In this manner, the memory
allocation method is isolated from the caller. Internally, the
NetApifunctions might be using
LocalAllocor
HeapAllocateor possibly even
newand
free.
It doesn't matter; as long as
NetApiBufferFreefrees the memory with the same allocator that
NetGroupEnumused to allocate the memory in the first place.
Although I personally prefer using a fixed external allocator, many people find it more convenient to use the wrapper technique. That way, they can use their favorite allocator throughout their module. Either way works. The point is that when memory
leaves your DLL, the code you gave the memory to must know how to free it, even if it's using a different compiler from the one that was used to build your DLL.
相关文章推荐
- DLL中用malloc分配了一块内存,但是在exe程序中释放引发的错误:其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。
- DLL中用malloc分配了一块内存,但是在exe程序中释放引发的错误:其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug
- DLL分配的内存如何在EXE里面释放
- DLL分配的内存如何在EXE里面释放
- DLL中用malloc分配了一块内存,但是在exe程序中释放引发的错误:其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。
- DLL中用malloc分配了一块内存,但是在exe程序中释放引发的错误可能原因
- DLL分配的内存如何在EXE里面释放
- 用vs2008写了一个动态库,其中有申请内存,用vc6.0写了一个exe调用动态库,并释放dll申请的内存:dbgheap.c Line:1011
- 跨DLL的内存分配释放问题 Heap corruption
- DLL中内存的分配释放
- Windows 下主程序与动态库(*.dll)释放对方分配的内存操作要点
- 在DLL中用CRT静态库申请内存,EXE释放是不行的
- 在DLL中用CRT静态库申请内存,EXE释放是不行的
- 用实例证明dll中new的内存不能在exe中释放
- 跨module(exe、dll)间传递c++对象发生申请/释放内存违例的问题
- 在DLL中用CRT静态库申请内存,EXE释放是不行的
- 一种在接口中跨dll分配释放内存的方法
- 用实例证明dll中new的内存不能在exe中释放
- 不同dll或者exe中释放内存
- 如何在Dll中分配内存,而在调用程序里释放