向LPARAM传递的对象属性赋值时触发读取访问违例
问题分析与解决方案
核心原因
你遇到的访问违例,本质是在IDOK分支中使用了无效的pState指针:DialogBoxParam传入的LPARAM仅在WM_INITDIALOG消息的lParam中有效,后续消息(如WM_COMMAND对应IDOK)的lParam是该消息的专属参数,并非初始传入的StateInfo指针。直接在IDOK分支中错误获取指针,自然会触发内存访问错误。
解决方案:将指针绑定到对话框窗口
无需全局变量,只需在WM_INITDIALOG时把pState指针存入对话框的窗口关联数据,IDOK分支再取出使用即可,有两种常用方式:
方式1:使用对话框专用额外数据(DWLP_USER)
操作简单,适合单数据存储场景:
BOOL CALLBACK NumberInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { // 保存StateInfo指针到对话框窗口数据 StateInfo* pState = reinterpret_cast<StateInfo*>(lParam); SetWindowLongPtr(hwndDlg, DWLP_USER, reinterpret_cast<LONG_PTR>(pState)); // 初始化控件值 SetDlgItemText(hwndDlg, IDC_EDIT_NUMBER, pState->N); return TRUE; } case WM_COMMAND: { if (LOWORD(wParam) == IDOK) { // 取出保存的指针 StateInfo* pState = reinterpret_cast<StateInfo*>(GetWindowLongPtr(hwndDlg, DWLP_USER)); if (!pState) break; // 读取对话框输入并更新状态 wchar_t inputBuf[256] = {0}; GetDlgItemText(hwndDlg, IDC_EDIT_NUMBER, inputBuf, _countof(inputBuf)); pState->N = inputBuf; // 若N是CString直接赋值即可 EndDialog(hwndDlg, IDOK); return TRUE; } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, IDCANCEL); return TRUE; } break; } } return FALSE; }
方式2:使用窗口属性(SetProp/GetProp)
适合需要存储多个关联数据的场景,记得在对话框销毁时清理:
BOOL CALLBACK NumberInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { StateInfo* pState = reinterpret_cast<StateInfo*>(lParam); // 用自定义属性名绑定指针 SetProp(hwndDlg, L"AppStateInfo", reinterpret_cast<HANDLE>(pState)); SetDlgItemText(hwndDlg, IDC_EDIT_NUMBER, pState->N); return TRUE; } case WM_COMMAND: { if (LOWORD(wParam) == IDOK) { StateInfo* pState = reinterpret_cast<StateInfo*>(GetProp(hwndDlg, L"AppStateInfo")); if (!pState) break; wchar_t inputBuf[256] = {0}; GetDlgItemText(hwndDlg, IDC_EDIT_NUMBER, inputBuf, _countof(inputBuf)); pState->N = inputBuf; EndDialog(hwndDlg, IDOK); return TRUE; } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, IDCANCEL); return TRUE; } break; } case WM_DESTROY: { // 清理绑定的属性,避免内存泄漏 RemoveProp(hwndDlg, L"AppStateInfo"); break; } } return FALSE; }
额外注意事项
- 确保
pState指向的StateInfo对象在对话框生命周期内始终有效(比如是堆分配的对象,或父窗口的成员变量),若对象提前销毁,即使存了指针也会触发访问违例。 - 使用
reinterpret_cast进行指针类型转换时,确保类型匹配,避免强制转换错误。
内容的提问来源于stack exchange,提问作者Lovro
相关产品推荐
相关产品推荐

