Memory is corrupt

Jul 3, 2021 at 1:22pm
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 Jul 4, 2021 at 12:43am
Jul 4, 2021 at 4:47pm
(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 Jul 4, 2021 at 6:42pm
Jul 5, 2021 at 10:35am
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"";
Jul 6, 2021 at 12:38am
pass a pre-allocated char/wide-char buffer to the DLL function instead of returning a C++ string
Jul 7, 2021 at 4:15am
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'
Jul 7, 2021 at 6:24pm
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 Jul 7, 2021 at 6:26pm
Jul 9, 2021 at 7:21am
Thank you Ganado !
Topic archived. No new replies allowed.