You've obviously come from another language that blends the concepts of pointers and references differently than C++. Your usage is wildly inappropriate in C++. You have complicated things further by using non-standard functions (HeapAlloc()
which is windows specific, not C++, etc) to manage memory.
If you are going to use HeapAlloc()
(which is non-standard C++, being windows specific) or any standard function that dynamically allocates memory, the result needs to be stored in a pointer.
MYSTRUCT ats = *(PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT));
wcscpy(ats.mystr, L"hello");
ats.threadHandle = CreateThread(NULL, 0, MyThread, &ats, 0, &(ats.threadId));
What this does is convert the pointer returned by HeapAlloc()
into a pointer to MYSTRUCT
, dereferences that pointer which interprets that memory location as the value of a MYSTRUCT
, and copies that value into ats
.
At the least this is a memory leak - the memory allocated by HeapAlloc()
is lost (never used again, it's address not stored anywhere), and you are passing the address of ats
to the thread function.
There is therefore NO RELATIONSHIP between the memory allocated by HeapAlloc()
and the address passed to the thread function.
Even worse is the thread function itself, which I've simplified here
DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT ActiveStruct = *(PMYSTRUCT)lpParam;
if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}
lpParam
is going to contain the address of ats
from the function that was passed by the function creating the thread.
If the function creating the thread has returned (after all, threads run in parallel) then that ats
will no longer exist. If that happens, lpParam
will be a dangling pointer (the address of an object that no longer exists as far as your program is concerned).
ActiveStruct
is now going to be a local object which contains a copy of the object at the address passed to the function. In other words, it is a local copy of ats
allocated previously by the func. If that ats
has ceased to exist, and the address passed is dangling, the simple act of creating ActiveStruct
causes undefined behaviour.
Even worse, lpParam
is the address of (what was) ats
. If ats
still exists (i.e. the function which created the thread hasn't returned), it was not created on the heap, so should not be released using HeapFree()
. If it no longer exists, then it shouldn't be passed to HeapFree()
either. Either way, HeapFree()
is being asked to release memory that was not allocated using HeapAlloc()
. That will be virtually guaranteed to cause a runtime error.
At minimum, you need to change the code which creates the thread to
MYSTRUCT *ats = (PMYSTRUCT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYSTRUCT)); // note changed position of *
wcscpy(ats->mystr, L"hello"); // note usage of ats as a pointer
DWORD threadID; // we need these since ats is being released by the thread function
HANDLE threadHandle; // it is not a good idea for CreateThread() to use them
threadHandle = CreateThread(NULL, 0, MyThread, ats, 0, &(threadId)); // changes since ats is now a pointer
and the thread function to
DWORD WINAPI MyThread(LPVOID lpParam)
{
MYSTRUCT *ActiveStruct = (PMYSTRUCT)lpParam; // this is now a pointer
if (lpParam != NULL)
{
std::cout << "1" << std::endl; // Gets printed.
HeapFree(GetProcessHeap(), NULL, lpParam);
std::cout << "2" << std::endl; // Crashes before this line.
}
}
Since you are making fundamentally wrong assumptions about the C++ memory model, I would assume other things (which you haven't shown) are wrong in your code. But this should get you started.