0

I want to raise this question one more time. I wrote a comment on the accepted answer already, but, it seems, the answered person is inactive on the SO. So, I copy my comment-question here.

In the accepted answer on the referred question, there is a potential risk of the memory leakage. For example, the PostMessage can be resulted with error because of the messages queue is full. Or, the target window may be already destroyed (so, the delete operator will not be called).

As a summary, there is no a strong corresponding between the posting and the receiving of the Windows message. But, on the other hand, there are not so many options how to pass a pointer (to a string, for example) with the Windows message. I see only two: to use objects allocated in the heap or declared as the global variables. The former one has the difficulty which is described here. The latter one is deprived of the specified disadvantage, but there is need to allocate some memory which may be used rarely.

So, I have these questions:

  1. May someone suggest a way, how we can be safe against the memory leakage in the case of using of the heap memory for "attaching" something to the Windows message?
  2. Is there some another option how we can reach the goal (send a string, for example, within the Windows message via the PostMessage system call)?
Serge Roussak
  • 1,731
  • 1
  • 14
  • 28
  • If `PostMessage` fails it returns `FALSE` and caller is responsible for freeing resources, if message has been posted successfully then recipient is responsible for freeing resources (target window getting destroyed is not a valid reason for message to be skipped or ignored). It's that simple. – user7860670 Sep 28 '21 at 09:03
  • @user7860670, excuse me, not quite understood you. What is the difference between "recipient" and "target window"? The window is actually the recipient, am I right? – Serge Roussak Sep 28 '21 at 09:17
  • 2
    You need to add the notion of ownership somewhere in your program. The string receiver could send an "acknowledge" message so the sender can free the string. Or pass a struct that contains a string and a counter that you set to 1 when send and the receiver will set to 0 when received, etc. After some timeout, the sender can free the string/struct anyway. – Simon Mourier Sep 28 '21 at 09:21
  • @SergeRoussak: The recipient of a message is primarily a thread - that's why windows have thread affinity. Those threads should have message pumps which dispatch window messages to the correct WindowProc. – MSalters Sep 28 '21 at 09:22
  • By "recipient" i mean code that handles target window messages and / or pumps messages for it. It should be written in the manner that ensures that all the messages that carry a pointer to allocated resource are processed and resources are properly disposed of. – user7860670 Sep 28 '21 at 09:30
  • Also, you might want to distinguish the various possible destinations of `PostMessage` : current thread, window in current thread, window in current process, or window in another process. `delete` appears to exclude the latter. – MSalters Sep 28 '21 at 09:30
  • Please explain what's *"unsafe"* about leaking resources? Or rather, what is your understanding of *"safe"*? – IInspectable Sep 28 '21 at 09:44
  • @IInspectable, mainly, I asked about a way how to post the Windows message and escape the memory leakage. – Serge Roussak Sep 28 '21 at 10:00
  • `PostMessage` is fire and forget. It doesn't provide any means of protecting against leaking resources. Maybe you are really looking for [SendMessageTimeout](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagetimeoutw). – IInspectable Sep 28 '21 at 10:50

1 Answers1

0

use std::wstringstream.
look for EM_STREAMOUT.

wchar_t remmi[1250];

//make stuff
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
     hc=CreateWindowEx(WS_EX_NOPARENTNOTIFY, MSFTEDIT_CLASS,remmi, 
        ES_MULTILINE|ES_AUTOVSCROLL| WS_VISIBLE | WS_CHILD 
        |WS_TABSTOP|WS_VSCROLL, 
        1, 350, 450, 201, 
        this->m_hWnd, NULL, h, NULL);
    return 0;
}

//middleware
DWORD CALLBACK E(DWORD_PTR dw, LPBYTE pb, LONG cb, LONG *pcb)
{
    std::wstringstream *fr = (std::wstringstream *)dw;
    fr->write((wchar_t *)pb, int(cb/2)); 
    *pcb = cb;
    return 0;
}

//final 
void CMainFrame::tr() 
{   
    std::wstringstream fr;
    EDITSTREAM es = {};
    es.dwCookie = (DWORD_PTR) &fr;
    es.pfnCallback = E;
    ::SendMessage(hc, EM_STREAMOUT, SF_TEXT|SF_UNICODE, (LPARAM)&es);       
    ZeroMemory(remmi,1218*2);
    fr.read(remmi,747);             
}