Memory is corrupt

DLL c++
1
2
3
4
5
extern "C"
{
    __declspec(dllexport) wstring ReadName(HWND hwnd);

}


c# to call
1
2
3
4
5
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern string ReadName(IntPtr hwnd);

IntPtr hWnd = FindWindow("Game Class", null);
string sName = ReadName(hWnd);


Error : Attempted to read or write protected memory. This is often an indication that other memory is corrupt
Last edited on
(1) Show the definition of ReadName. What is happening inside it?
(2) What is a wstring in your non-C# code? Surely it's not a C++ std::wstring, because you're exporting it as C code. You need to give more details, but I think this is the main problem.

A common way to do this is to pass a pre-allocated char/wide-char buffer to the DLL function instead of returning a C++ string. On the C# side you can use a StringBuilder.

Here are some pages that gives more details:
https://stackoverflow.com/questions/20752001/passing-strings-from-c-sharp-to-c-dll-and-back-minimal-example
https://limbioliong.wordpress.com/2011/06/16/returning-strings-from-a-c-api/
https://social.msdn.microsoft.com/Forums/vstudio/en-US/97000354-0ade-4cb7-affa-d8567412c10b/returning-arrays-from-c-dll-with-extern-quotcquot-to-c

I'd give a full C++/C# example but don't have the resources available right now.
Last edited on
Thank you Ganado for your reply

1
2
3
4
5
6
7
8
9
10
wstring ReadName(HWND hwnd, int idx)
{
	wstring sName = L"";
	DWORD pid;
	HANDLE pHandle;
	SYSTEM_INFO si;
	MEMORY_BASIC_INFORMATION mbi;
	DWORD ret, totalRead;
	...
}


Error : wstring sName = L"";
pass a pre-allocated char/wide-char buffer to the DLL function instead of returning a C++ string
DLL c ++
1
2
3
4
5
6
wchar_t* ReadName(HWND hwnd, int idx)
{
	wstring sName = L"Hello";
	wchar_t* ptr = _wcsdup(sName.c_str());
	return ptr;
}


C# to call
1
2
3
4
5
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern StringBuilder ReadName(IntPtr hwnd);

IntPtr hWnd = FindWindow("Game Class", null);
string sName = ReadName(hWnd).ToString();


I only get 'H' but not 'Hello'
Dealing with memory/pointers between unmanaged land and managed land is tricky.
I don't suggest using _wcsdup because if I'm not mistaken, you're basically creating a memory leak each time you call ReadName, since you can't free the memory from the C# side.

Again, I would have a parameter in ReadName that is a pre-allocated buffer on the C# side, that way you aren't allocating any memory within ReadName.

But for your current code, to convert the pointer from C++ to a proper C# string, you need to use a function like PtrToStringAuto, which takes in the pointer (the wchar_t* on the C++ side).

1
2
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ReadName(IntPtr hwnd);


1
2
3
IntPtr hWnd = IntPtr.Zero; // just for test
string sName = Marshal.PtrToStringAuto(ReadName(hWnd));
Console.WriteLine(sName); // prints "Hello" 
Last edited on
Thank you Ganado !
Topic archived. No new replies allowed.