Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which are the safe way to send CString through PostMessage from thread

What is the safe / best way to send a CString through PostMessage, from a thread ? To create CString on heap and clean up when the receiver get this CString ?

Solution 1: In thread:

CString* pError = new CString(_T("Unknown error"));
::PostMessage(...(LPARAM)pError);

and in main thread, somewhere in GUI:

CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);
delete pError;

Solution 2: Or, to keep CString object as member variable inside of CThread class ?

class CPlanThread : public CThread [: public CObject]
{
public:
DECLARE_DYNAMIC(CPlanThread)

...
protected:
CString* m_pMessage;

};

and

CPlanThread::CPlanThread()
:m_pMessage(NULL)
{
m_pMessage = new CString(_T(""));
}

CPlanThread::~CPlanThread()
{
if(NULL != m_pMessage)
    delete m_pMessage;
}

and somewhere in thread:

::PostMessage(m_hWndMain, WMU_NOTIFYTHREAD, 0, (LPARAM)m_pMessage);

and in main thread, somewhere in GUI:

CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);

Both of the above solutions are safe ? Kindly thank you for any explanation.

like image 622
Flaviu_ Avatar asked Feb 07 '17 09:02

Flaviu_


1 Answers

The first option is the safer alternative.* The only reason, why this could result in a resource leak is, if the call to ::PostMessage fails, and you aren't cleaning up in the sender. Note, that this does not lead to a crash.

The second alternative creates a race condition, since you are holding on to a pointer, whose ownership you meant to transfer. If the GUI thread tries access the string after the thread objects has been destroyed, you are accessing random memory. This can lead to an immediate crash, if you are lucky.

Depending on your specific use case, you might want to consider using a third alternative: Using a CString object with automatic storage duration and thread synchronization through message-sending, e.g.:

CStringW err( L"Unknown error" );
::SendMessage( ..., (LPARAM)&err );

The receiving thread can use the string object for as long as it is in its message handler, and the sender will automatically clean up the resource.


*That is assuming, that both threads are implemented in the same module. Make sure to read Potential Errors Passing CRT Objects Across DLL Boundaries in case they aren't.
like image 87
IInspectable Avatar answered Sep 22 '22 16:09

IInspectable