No, you cannot just use whatever method you want to free memory. You MUST use whatever the allocator requires you to use. Only the memory manager that allocates a given block of memory knows how to free that block of memory properly.
For instance, the documentation for Marshal.AllocHGlobal() states:
This method exposes the Win32 LocalAlloc function from Kernel32.dll.
When AllocHGlobal calls LocalAlloc, it passes a LMEM_FIXED flag, which causes the allocated memory to be locked in place. Also, the allocated memory is not zero-filled.
And the documentation for LocalAlloc() states:
To free the memory, use the LocalFree function. It is not safe to free memory allocated with LocalAlloc using GlobalFree.
Which is what Marshal.FreeHGlobal() uses:
FreeHGlobal exposes the LocalFree function from Kernel32.DLL, which frees all bytes so that you can no longer use the memory pointed to by hglobal.
So, it is allowed for C# code to allocate memory using Marshal.AllocHGlobal() and then for C++ code to free that memory using LocalFree(). And conversely, for C++ code to allocate memory using LocalAlloc(LMEM_FIXED) and then for C# code to free that memory using Marshal.FreeHGlobal().
Likewise, the Marshal class also has a Marshal.AllocCoTaskMem() method:
This method exposes the COM CoTaskMemAlloc function, which is referred to as the COM task memory allocator.
Memory allocated by CoTaskMemAlloc() is freed with CoTaskMemFree():
Frees a block of task memory previously allocated through a call to the CoTaskMemAlloc or CoTaskMemRealloc function.
Which is what Marshal.FreeCoTaskMem() uses :
FreeCoTaskMem exposes the COM CoTaskMemFree function, which frees all bytes so that you can no longer use the memory that the ptr parameter points to.
So, it is allowed for C# code to allocate memory using Marshal.AllocCoTaskMem() and then for C++ code to free that memory using CoTaskMemFree(). And conversely, for C++ code to allocate memory using CoTaskMemAlloc() and then for C# code to free that memory using Marshal.FreeCoTaskMem().
Now, that being said, the memory manager that C++ uses for its new and delete operators is implementation-defined. There is no guarantee (or likelihood) that new uses LocalAlloc() or CoTaskMemAlloc(), or that delete uses LocalFree() or CoTaskMemFree().
So, it is not legal for C# to free any memory allocated with new, or for C++ to delete any memory allocated by C#.