Freeing memory allocated in a different DLL

I have an EXE file using a DLL file which is using another DLL file. This situation has arisen:

In DLL file 1:

class abc
{
    static bool FindSubFolders(const std::string & sFolderToCheck, 
                               std::vector< std::string > & vecSubFoldersFound);
}

In DLL file 2:

void aFunction()
{
    std::vector<std::string> folders;
    std::string sLocation;
    ...
    abc::FindSubFolders(sLocation, folders)
}

In release mode, everything works fine. But in debug mode, I come up with an assertion failure in the destructor of one of the std::strings in the folders vector (when folders goes out of scope at the end of aFunction):

dbgheap.c : line 1274

/*
 * If this ASSERT fails, a bad pointer has been passed in. It may be
 * totally bogus, or it may have been allocated from another heap.
 * The pointer MUST come from the 'local' heap.
 */
_ASSERTE(_CrtIsValidHeapPointer(pUserData));

I assume this is because the memory has been allocated on DLL file 1's heap, but is being freed in DLL file 2.

The comment in dbgheap.c seems pretty insistent that this is a problem.

Why is this such a problem, when it seems to work fine if I just ignore it? Is there a non-assertion-failing way of doing this?


As sean has already said, the release build simply ignores that delete statement, so the best you can hope for is a memory leak.

If you have control over how both DLL files are compiled, make sure to use the Multi-threaded Debug DLL (/MDd) or Multi-threaded DLL (/MD) settings for the runtime library. That way, both DLL files will use the same runtime system and share the same heap.

The downside is that you need to install the runtime system together with your application (Microsoft offers an installer for that). It will work fine on your development machine since Visual Studio installs that runtime system too, but on a freshly installed machine it will report missing DLL files.


As other says, the problem can be solved by making sure that the CRT is shared between the two modules. But there are common scenarios where this contract is hard to enforce.

The reason is that making sure to link against a shared CRT will not work if the EXE and DLL do not link against the same CRT version (as in 6.0, 7.0, 8.0). For example if you take a DLL that has been built in VC6.0 and try to use it with an EXE build in VS2010 you will get the same issue as before. The two versions of CRT will be loaded in your process and will each use their own heap for allocation, regardless if your EXE and DLL use 'shared' CRT, they will not be the same.

A better practice for an API would be to make sure that objects allocated in one side are also destroyed on the same side. I know this sounds ugly but it is the only way to ensure that a DLL remains binary compatible.


Most likely, the release build has the same problem, but release builds don't assert. They just ignore the problem. You might never see an issue. Or you might see data corruption. Or you might see a crash. Maybe only your users will experience bugs that you are simply not able to reproduce.

Don't ignore CRT assertions.

You should always use the appropriate deallocator (the one that matches the allocator used to begin with). If you are using static CRT libraries in your DLL files, the DLL files are using different heaps. You can not deallocate memory across heaps. Allocate and deallocate a block of memory using the same heap.

If you are using shared CRT libraries in your DLL files, then they should be using the same heap and you can allocate in one DLL file and deallocate in another.

链接地址: http://www.djcxy.com/p/14442.html

上一篇: 堆Win32下的腐败; 如何定位?

下一篇: 释放分配在不同DLL中的内存