我显然很晚才参加聚会,但我想我会分享我在这个问题上的经验,以试图阐明一些观点。
我目前正在开发一个包装 Windows API 功能的轻量级窗口库。
我最顶层的 Window 类的声明包括一个指向 CHAR 数组基地址的指针,该数组表示 WNDCLASSEX 类名和相应窗口的标题。此字符串在堆上分配,并始终在 Window 的构造函数中复制,以避免在销毁 Window 对象时取消注册 NULL 类名。Window 的析构函数还在 CHAR 缓冲区上调用 delete[]。
当我开始实现与一个或多个 Window(或派生类)实例一起使用的独立消息处理函数时,第一次出现问题。循环如下:
DWORD win_api::BeginQueueingMessages
(
Window const * windowList,
UINT length,
INT showCommandIndex
)
{
BOOL processMessages = TRUE;
BOOL isFirstIteration = TRUE;
while (processMessages)
{
for (UINT i = 0; i < length; ++i)
{
Window window = windowList[i];
HWND handle = window.getHandle();
MSG message = {};
if (isFirstIteration)
{
ShowWindow(handle, showCommandIndex);
UpdateWindow(handle);
isFirstIteration = FALSE;
}
if (GetMessage(&message, handle, NULL, NULL))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
else
{
processMessages = FALSE;
}
}
}
return 0;
}
我最终确定了以下代码行是罪魁祸首:
Window window = windowList[i];
我错误地调用了由赋值运算符触发的自动实现的复制构造函数。因此,左侧运算符的内部 CHAR 指针现在指向与 windowList[i] 的成员相同的位置,而无需分配新的堆内存。
稍后,在程序终止期间,在未初始化的内存块上调用 delete[] 并引发 C 运行时异常。
我希望这有帮助。