将 CString::GetString() 与 CWnd::SendMessage() 一起使用是不是安全?
Posted
技术标签:
【中文标题】将 CString::GetString() 与 CWnd::SendMessage() 一起使用是不是安全?【英文标题】:Is it safe to use CString::GetString() with CWnd::SendMessage()?将 CString::GetString() 与 CWnd::SendMessage() 一起使用是否安全? 【发布时间】:2021-11-07 06:37:10 【问题描述】:我有这个代码:
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;
【问题讨论】:
这取决于 UWM_DELETE_NAME_HISTORY_MSG 的消息处理程序的作用。 标题说PostMessage,问题问SendMessage,下定决心,Send safe时Post可能不安全static_cast<WPARAM>(strName.GetString())
不会编译。您需要reinterpret_cast
才能从指针转到 WPARAM。是的,您需要对标准 Windows 消息执行大量 reinterpret_cast<LPARAM>(string)
处理,这些消息将 char*
作为 Lparam。
【参考方案1】:
SendMessage
是一个阻塞调用。一旦它返回,它就不再需要访问它的参数。考虑到这一点
GetParent()->SendMessage(UWM_DELETE_NAME_HISTORY_MSG, (WPARAM)strName.GetString());
是安全的(就SendMessage
调用而言)。
您仍然需要小心UWM_DELETE_NAME_HISTORY_MSG
消息(可能是自定义消息)的实现者。如果实现存储了一个指针并在处理程序运行完成后使用它,那么这是一个需要解决的问题。
一般来说,如果您实现消息处理程序,您应该遵循 Windows API 的核心原则。最终有两种实现方式:
存储客户端提供数据的副本(例如SetWindowTextW
)。
返回对先前值的引用,以防 API 获得客户端提供的数据的所有权(例如 SelectObject
)。
【讨论】:
谢谢。为了完整性,我添加了自定义消息处理程序。我认为现在一切都好。唯一的区别是我使用了reinterpret_cast<WPARAM>
。【参考方案2】:
在标题中回答您的问题:
将 CString::GetString() 与 CWnd::POstMessage() 一起使用是否安全?
不,不是 - 在处理消息时,CString
的内容可能会被重新分配或删除。
【讨论】:
我的标题是说 SendMessage。很抱歉我的疏忽。 @AndrewTruckle 哦,那就在 cmets 中回答了。以上是关于将 CString::GetString() 与 CWnd::SendMessage() 一起使用是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - Sharedaddy
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - 分享此功能
php [将产品与社交共享插件集成]将社交共享插件与WooCommerce集成 - 分享此功能