考虑以下代码片段:
// MyWindow.h
struct MyWindow
{
LRESULT CALLBACK myWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK myWindowProcWrapper(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
extern MyWindow *windowPtr; // windowPtr is initialized on startup using raw new
// MyWindow.cpp
MyWindow *windowPtr = 0;
LRESULT CALLBACK MyWindow::myWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_NCDESTROY:
delete windowPtr;
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK MyWindow::myWindowProcWrapper(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return windowPtr->myWindowProc(hwnd, msg, wParam, lParam);
}
Run Code Online (Sandbox Code Playgroud)
问题是给定的代码片段如所编写的那样是否安全。
基本上,MyWindow是使用WinAPI创建的窗口的类。当窗口被破坏时,我需要做一些最后的清理。
请注意,实例MyWindow,windowPtr被使用原始创建new。我必须在成员函数中的某处删除实例,因此我从成员函数中删除了对对象本身的引用。
该代码依赖于该WM_NCDESTROY窗口曾经接收到的最后一条消息的假设。
因此,问题如下:
WM_NCDESTROY窗口始终是接收到的最后一条消息并在那里执行最终清除?备注:我只对代码在技术上是否安全感兴趣,而不是对使用原始的新变量和/或全局变量是否是一种好的做法,不感兴趣。我有一些很好的理由执行此操作。
它没有明确记录,这WM_NCDESTROY是窗口收到的最后一条消息。但是,如果您在两行之间阅读,则可以推断出此信息。
WM_NCDESTROY的文档包含以下说明:
此消息释放为窗口内部分配的所有内存。
窗口功能:窗口破坏概述了这种情况的后果:
窗户被破坏时,系统会删除与窗户相关的所有内部数据。这会使窗口句柄无效,该窗口句柄不能再由应用程序使用。
将它们放在一起,破坏一个窗口会使它的窗口句柄失效。一旦WM_NCDESTROY消息处理程序已完成运行,窗口句柄不再有效。无效的窗口句柄不再接收任何消息。
因此,您的实施是安全的。
令人怀疑的是,这些规则中的任何WM_NCDESTROY一条将来是否会更改(有那么多应用程序依赖于最终消息),但是如果您要做好准备,则可能需要考虑在windowPtr = nullptr;后面放置一条语句delete windowPtr;。这样做可以确保您的应用程序以可预见的方式失败,以防在MyWindow实例被处置后收到消息。
| 归档时间: |
|
| 查看次数: |
440 次 |
| 最近记录: |