I have a chunk of code that I'm using to get the UNC path of a mapped drive in a CLR DLL, but when I'm freeing memory at the end, a char array causes an invalid heap pointer assertion failure, and I'm assuming it has to do with it being allocated by InteropServices, but I want to make sure it doesn't turn into a memory leak as this function gets called repeatedly.
Code:
DWORD MAX_DEVICE_LENGTH = 1000;
TCHAR* szDeviceName = new TCHAR[MAX_DEVICE_LENGTH];
memset(szDeviceName, '\0', MAX_DEVICE_LENGTH);
DWORD dwResult;
char* charpath = (char*) (void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(path->Substring(0,2));
wchar_t* tpath = new wchar_t[MAX_DEVICE_LENGTH];
memset(tpath, '\0', MAX_DEVICE_LENGTH);
DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, charpath, -1, NULL, 0);
M开发者_开发知识库ultiByteToWideChar (CP_ACP, 0, charpath, -1, tpath, dwNum );
dwResult = WNetGetConnection(
tpath,
szDeviceName, &MAX_DEVICE_LENGTH);
System::String ^ str = gcnew System::String(szDeviceName);
str += path->Substring(2, path->Length-2);
delete(szDeviceName);
free(charpath); //This is where it assert-fails
delete(tpath);
return str;
It's probably something basic about memory de-allocation that I don't understand, but either way it's worth figuring out. If it helps, if I skip over that line tpath deletes fine, but if the charpath assertion fails then tpath will fail as well.
The relevant comment on MSDN is
StringToHGlobalAnsi is useful for custom marshaling or when mixing managed and unmanaged code. Because this method allocates the unmanaged memory required for a string, always free the memory by calling FreeHGlobal. StringToHGlobalAnsi provides the opposite functionality of Marshal.PtrToStringAnsi.
So, no delete/free but FreeHGlobal
.
For szDeviceName
and tpath
use delete[]
instead of delete
. []
version is for arrays and non-[]
version is for single objects.
According to MSDN, you should be freeing the memory with FreeHGlobal
This is just wrong:
free(charpath);
Since charpath
was allocated by StringToHGlobalAnsi
you should call FreeHGlobal
. Like this:
Marshal::FreeHGlobal(IntPtr(charpath));
精彩评论