使用 CString::GetString() 和 CWnd::SendMessage() 是否安全?

Is it safe to use CString::GetString() with CWnd::SendMessage()?

我有这个代码:

GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetBufferSetLength(_MAX_PATH));
strName.ReleaseBuffer();

我这样改安全吗:

GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetString());

与此相关,使用static_cast<WPARAM>(strName.GetString())是否正确?


为了完成,这是我的自定义消息处理程序:

LRESULT CChristianLifeMinistryEditorDlg::OnDeleteNameHistory(WPARAM wParam, LPARAM lParam)
{
    auto szName = (LPCTSTR)wParam;

    m_History.erase(szName);

    for (auto& kv : m_mapWeekendHistData)
        kv.second.erase(szName);

    return 0;
}

回答标题中的问题:

Is it safe to use CString::GetString() with CWnd::POstMessage()?

不,不是 - CString 的内容可能会在处理邮件时重新分配或删除。

SendMessage 是阻塞调用。一旦它 returns,它就不再需要访问它的参数。考虑到这一点

GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetString());

是安全的(就 SendMessage 调用而言)。

您仍然需要注意 UWM_DELETE_NAME_HISTORY_MSG 消息(大概是自定义消息)的实现者。如果实现存储一个指针并在处理程序 运行 完成后使用它,那么这是一个需要解决的问题。

一般来说,如果您实现消息处理程序,您应该遵循Windows API 的核心原则。最终有两种实现:

  • 存储客户提供的数据的副本(例如SetWindowTextW)。
  • Return 对先前值的引用,以防 API 获得客户端提供的数据的所有权(例如 SelectObject)。