Повреждение кучи при использовании CreateWindowExW

У меня есть некоторые проблемы с повреждением кучи. Предупреждение можно наблюдать при использовании функции 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 возвращает ненулевое значение, и окно создается так, как должно быть...


person Tiffany    schedule 27.02.2014    source источник
comment
Повреждение кучи часто проявляется после того, как оно произошло, поэтому эта функция может просто указывать на проблему и вообще не иметь к ней отношения. Посмотрите, что вы сделали, прежде чем назвать это.   -  person Retired Ninja    schedule 27.02.2014
comment
Знание всего безумия, происходящего в вашем WndProc, потенциально может рассказать о том, что может повредить вашу кучу.   -  person WhozCraig    schedule 27.02.2014
comment
Повреждение кучи могло произойти до вызова CreateWindowEx или во время оценки любого из его аргументов (например, g_config->GetWndClass()), или это могло произойти в одном из обработчиков сообщений, вызываемых во время создания окна (например, WM_CREATE). Вам придется сузить его.   -  person Adrian McCarthy    schedule 27.02.2014
comment
По моему опыту, это часто происходит из-за неправильной очистки памяти, обычно из-за того, что указатель на память устарел, что портит память.   -  person RoG    schedule 16.01.2017


Ответы (2)


Как указывалось выше, повреждение кучи часто обнаруживается после того, как реальное повреждение уже произошло какой-либо DLL/модулем, загруженным в ваш процесс. Из вашего сообщения видно, что эта проблема зависит от платформы Windows, поэтому я предлагаю вам использовать WinDBG/Pageheap и выяснить, где происходит фактическое повреждение памяти. Одну очень хорошую статью об анализе повреждения памяти в куче можно найти в книге «Расширенная отладка Windows, автор: Марио Хьюардт; Даниэль Прават», глава 06.

http://advancedwindowsdebugging.com/ch06.pdf

person Mantosh Kumar    schedule 27.02.2014
comment
Эта книга просто выдающаяся, кстати. - person WhozCraig; 28.02.2014
comment
Что ж, вы все были правы: сделка не была связана с CreateWindowExW. Я использовал WinDBG и Application Verifier и отладчик VS. Так что углубился и обнаружил, что причина была совсем в другой функции при попытке освободить кучу. Спасибо - person Tiffany; 17.03.2014

Изменять

WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };

to

WNDCLASSEX wcex = { 0 };

Вы инициализируете члены-указатели WNDCLASSEX ненулевыми (но бессмысленными значениями, а именно sizeof(WNDCLASSEX)).

person heinrichj    schedule 27.02.2014
comment
Нет, это не так. нулевое значение хвостовой инициализации заполняет оставшиеся неуказанные элементы. - person WhozCraig; 27.02.2014