关于std::unique_ptr自动释放内存的疑问:Windows消息传递场景下的对象释放问题
关于std::unique_ptr自动释放内存的疑问:Windows消息传递场景下的对象释放问题
嘿,这个场景我熟,直接给你结论:只要你在消息处理函数里正确用std::unique_ptr接管了那个new出来的对象,当处理函数返回时,这个对象肯定会被自动释放。
咱们一步步拆解整个流程,你就明白为啥了:
- 首先你用
new BackupStatusMsg{...}在堆上分配了对象,然后通过PostMessage把地址发出去——这里要记得PostMessage是异步的,发完就返回,不会等消息被处理。 - 当窗口的消息队列轮到处理
WM_BACKUP_STATUS时,你的DialogClass::OnBackupStatus(应该是你打错成OnSo了吧😉)函数会被调用,你把LPARAM转成原始指针,用它初始化std::unique_ptr。这一步非常关键:从这一刻起,std::unique_ptr就完全接管了这个堆对象的所有权,原始指针就不该再被用来操作这个对象了。 - 当消息处理函数执行完毕,函数里的
std::unique_ptr局部变量会离开它的作用域,这时候std::unique_ptr的析构函数会自动触发,调用delete释放它管理的那个BackupStatusMsg对象,内存就被正确回收了。
给你把代码补全更清楚:
发送消息的代码:
auto* data = new BackupStatusMsg{ pct, st, e1, e2, msg }; ::PostMessage(m_hWnd, WM_BACKUP_STATUS, 0, reinterpret_cast<LPARAM>(data));
消息处理函数里的代码(假设你是这么写的):
LRESULT DialogClass::OnBackupStatus(WPARAM wParam, LPARAM lParam) { // 把LPARAM转回原始指针,用它初始化unique_ptr std::unique_ptr<BackupStatusMsg> msgData(reinterpret_cast<BackupStatusMsg*>(lParam)); // 这里用msgData做你要的操作,比如访问它的成员 // ... // 函数返回时,msgData离开作用域,自动调用delete释放对象 return 0; }
不过有两个坑得提前踩住:
- 绝对不能让其他智能指针或者原始指针再去释放这个对象,不然会触发**重复释放(double free)**的崩溃——毕竟unique_ptr的核心就是独占所有权。
- 要确保窗口在消息被处理前不会被销毁!如果窗口提前关了,
PostMessage的消息可能会被系统丢弃,那你new出来的对象就没人接管了,直接内存泄漏。这种情况你可以先判断PostMessage的返回值,如果返回0说明消息没发出去,这时候要手动delete那个data,避免泄漏。
内容来源于stack exchange
相关产品推荐
相关产品推荐

