views:

98

answers:

4

Recently I heard that memory in the stack is not shared with other thread and memory in the heap is shared with other threads.

I normally do:

HWND otherThreadHwnd;
DWORD commandId;
// initialize commandId and otherThreadHwnd

struct MyData {
  int data1_;
  long data2_;
  void* chunk_;
};

int abc() {
  MyData myData;
  // initialize myData
  SendMessage(otherThreadHwnd,commandId,&myData);
  // read myData
}

Is it alright to do this?

+3  A: 

Yes, it is safe in this instance.

Data on the stack only exists for the lifetime of the function call. Since SendMessage is a synchronous, blocking call, the data will be valid for the duration of that call.

This code would be broken if you replace SendMessage with a call to PostMessage, SendNotifyMessage, or SendMessageCallback, since they would not block and the function may have returned before the target window received the message.

Michael
Watch out for ReplyMessage ( http://msdn.microsoft.com/en-us/library/ms644948%28VS.85%29.aspx ) though - see this question http://stackoverflow.com/questions/1882351/can-sendmessage-return-early-if-the-receiving-thread-starts-pumping-messages/1883916
sean e
I think it'd be a bug in the WndProc if it calls ReplyMessage but does not capture the arguments passed to it beforehand.
Michael
Or an incorrect assumption on the caller's part.
sean e
+2  A: 

Yes, it is okay.

SendMessage is working in blocking mode. Even if myData is allocated in stack, its address is still visible to all threads in the process. Each thread has its own private stack; but data in the stack can be explicitly shared, for example, by your code. However, as you guess, do not use PostThreadMessage in such case.

minjang
+2  A: 

I think 2 different issues are being confused by whoever you "heard that memory in the stack is not shared with other thread":

  1. object lifetime - the data on the stack is only valid as long the thread doesn't leave the scope of the variable's name. In the example you giove, you're handling this by making the call to the other thread synchronously.

  2. memory address visibility - the addresses pspace for a process is shared among the various threads in that process. So variables addressable by one thread are addressable by other threads in that process. If you are passing the address to a thread in a different process, the situation is quite different and you'd need to use some other mechanism (which might be to ensure that the memory block is mapped into both processes - but that I don't think that can normally be done with stack memory).

Michael Burr
afriza
@afriza: the answer to both your questions is yes. Some weasel words: strictly speaking both of those items are platform specific, but for the process models of modern 32-bit desktop operating systems (or better), such as Linux or Windows, the answers are "yes".
Michael Burr
A: 

What you heard about is "potential infringement of privacy", which is sharing the data on one thread's private stack with another thread.

Although it is not encouraged, it is only a "potential" problem--with correct synchronization, it can be done safely. In your case, this synchronization is done by ::SendMessage(); it will not return until the message is processed in the other thread, so the data will not go out of scope on the main thread's stack. But beware that whatever you do with this pointer in the worker thread, it must be done before returning from the message handler (if you're storing it somewhere, be sure to make a copy).

Nikola Gedelovski