Здравствуйте, коллеги.
Переносил старый проект на x64 и обнаружил баг в коде MFC.
Код грузит из ресурсов DLL шаблон диалога и передает HTEMPLATE конструктору CDialogTemplate.
HRSRC hres = ::FindResource(hmod, MAKEINTRESOURCE(template_id), RT_DIALOG);
HGLOBAL ht = ::LoadResource(hmod, hres);
CDialogTemplate templ(ht); // << здесь AV
// работаем с templ
В сборке x86 много лет все работает ок, а в сборке x64 только для одного из диалогов в конструкторе AV.
Долго протирал глаза и сравнивал, чем этот диалог отличается от остальных. Переставлял местами, менял значение resource id — все без толку.
Оказалось, что в файле dlgtempl.cpp 119 вместо LockResource зовется GlobalLock/GlobalUnlock.
DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate);
В описании LoadResource явно сказано, что HGLOBAL возвращается не настоящий)).
Для него применимы только LockResource и SizeOfResource...
Для проблемного диалога GlobalLock возвращает NULL (который потом не проверялся, поэтому AV) и
код ошибки 6 — неверный дескриптор.
Проблема рещилась самостоятельным вызовом LockResource и использованием другого конструктора:
HRSRC hres = ::FindResource(hmod, MAKEINTRESOURCE(template_id), RT_DIALOG);
HGLOBAL ht = ::LoadResource(hmod, hres);
const DLGTEMPLATE* pt = static_cast<const DLGTEMPLATE*>(::LockResource(ht));
CDialogTemplate templ(pt);
// работаем с templ
Будьте бдительны!
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!