【问题标题】:Heap Corruption while using CreateWindowExW使用 CreateWindowExW 时的堆损坏
【发布时间】:2014-03-31 03:18:48
【问题描述】:

我遇到了一些堆损坏问题。使用 CreateWindowExW 函数时可以观察到警告。我知道这通常是一个内存错误,但是在这种情况下我怎么能找到它呢?在调用 CreateWindowExW 之前没有新变量,我无法进入此函数。这是代码。

HWND GetMainWnd(HINSTANCE hInstance){
static HWND hWnd = NULL;
if (hWnd)
    return hWnd;

RETURN_AT_ERROR(hInstance, NULL);

WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style          = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    = MainWndProc;
wcex.hInstance      = hInstance;
wcex.hCursor        = ::LoadCursorW(NULL, IDC_ARROW);
wcex.lpszClassName  = g_config->GetWndClass();

ATOM atom = ::RegisterClassExW(&wcex);
RETURN_AT_ERROR(atom != 0, NULL);

hWnd = ::CreateWindowExW(WS_EX_LEFT, g_config->GetWndClass(), 0, WS_POPUP | WS_MINIMIZEBOX | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, hInstance, 0);

return hWnd;}

在这个字符串上

hWnd = ::CreateWindowExW(WS_EX_LEFT, g_config->GetWndClass(), 0, WS_POPUP | WS_MINIMIZEBOX | WS_CLIPCHILDREN, 0, 0, 0, 0, 0, 0, hInstance, 0);

有一个警告消息框

Windows 已在 drm.exe 中触发断点。这可能是由于一个 堆损坏,这表明 drm.exe 或任何 它已加载的 DLL。这也可能是由于用户按 F12 而 drm.exe 有焦点。输出窗口可能有更多诊断 信息。

我按“继续”,它会显示

Unhandled exception at 0x77dae753 in app.exe: 0xC0000374: A heap has been corrupted.

然而 CreateWindowExW 返回一个非零值,并且窗口被创建为它应该是的......

【问题讨论】:

  • 堆损坏通常是在它发生之后才出现的,所以这个函数可能只是指出问题所在,与它无关。看看你在打电话之前做了什么。
  • 了解你的 WndProc 中的所有疯狂可能会说明什么可能会破坏你的堆。
  • 堆损坏可能发生在调用 CreateWindowEx 之前,或者在评估其任何参数期间(例如,g_config->GetWndClass()),或者它可能发生在调用期间调用的消息处理程序之一中窗口创建(如 WM_CREATE)。您必须缩小范围。
  • 根据我的经验,这通常是由于不正确地清除内存,通常是因为指向内存的指针已过期,从而损坏了内存。

标签: c++ visual-studio-2010 heap-corruption


【解决方案1】:

如上所述,堆损坏通常是在您的进程中加载​​的某些 DLL/模块已经发生真正损坏之后检测到的。从您的帖子看来,此问题是特定于 Windows 平台的,因此我建议您使用 WinDBG/Pageheap 并找出实际内存损坏发生的位置。一篇关于堆内存损坏分析的非常好的文章可以从《高级 Windows 调试》一书中找到,作者:作者:Mario Hewardt;Daniel Pravat" Chapter 06

http://advancedwindowsdebugging.com/ch06.pdf

【讨论】:

  • 那本书简直是优秀,顺便说一句。
  • 嗯,你们都是对的:这笔交易与 CreateWindowExW 无关。我使用了 WinDBG 和 Application Verifier 和 VS 调试器。所以更深入地发现原因绝对是另一个函数,同时试图释放堆。谢谢
【解决方案2】:

改变

WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };

WNDCLASSEX wcex = { 0 };

您正在将 WNDCLASSEX 的指针成员初始化为非空值(但无意义的值,即 sizeof(WNDCLASSEX))。

【讨论】:

  • 不,他不是。尾初始化零填充剩余的未指定成员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 2010-11-15
相关资源
最近更新 更多