Вебинар: Парсим С++ - 25.10
Об одной проблеме при миграции кода на 64-битные системы, связанной с некорректной перегрузкой виртуальных функций мы писали в наших статьях уже давно. Например, наша статья "20 ловушек переноса Си++ - кода на 64-битную платформу" вышла в марте 2007 года (хотя ничуть не утратила актуальности). В ней было описание проблемы с виртуальными функциями.
Суть проблемы заключается в следующем. С незапамятных времен в библиотеке MFC есть класс CWinApp, в котором имеется функция WinHelp:
class CWinApp {
...
virtual void WinHelp(DWORD dwData, UINT nCmd);
};
Для показа собственной справки в пользовательском приложении необходимо было эту функцию перекрыть:
class CSampleApp : public CWinApp {
...
virtual void WinHelp(DWORD dwData, UINT nCmd);
};
И все было прекрасно до тех пор, пока не появились 64-битные системы. Тогда разработчикам MFC пришлось поменять интерфейс функции WinHelp (и некоторых других) так:
class CWinApp {
...
virtual void WinHelp(DWORD_PTR dwData, UINT nCmd);
};
В 32-битном режиме типы DWORD_PTR и DWORD совпадали, а вот в 64-битном... Естественно разработчики пользовательского приложения тоже должны были сменить тип на DWORD_PTR для корректной перегрузки, но компилятор про это не говорил, и ошибка выявлялась только на этапе тестирования, когда справочная система вела себя "загадочно". За подробностями я отсылаю читателя к упомянутой выше статье.
Вспомнить эту ошибку меня заставил тот факт, что сегодня, в конце 2009 года эта ошибка до сих пор есть в коде реальных приложений. Сомневаетесь?
Есть прекрасная библиотека компонентов BCGControlBar. Наверняка вы про нее слышали, поскольку компоненты компании BCGSoft Ltd включены в Microsoft Visual Studio 2008 Feature Pack. Так вот, если скачать ознакомительную версию этой библиотеки, установить ее и выполнить поиск слова "WinHelp" по .h-файлам... то мы увидим, что везде, где якобы перекрыта эта функция, используется параметр DWORD, вместо DWORD_PTR. А это означает, что справка в 64-битной системе в этих классах будет вести себя некорректно.
Неужели подобная ошибка может до сих пор быть в коде такой известной библиотеки? Я думаю дело в том, что клиентам компании доступны исходные коды этой библиотеки и клиенты всегда могут поправить эти коды. Кроме того, в настоящее время функция WinHelp используется очень редко. Намного чаще используется HtmlHelp. А она-то в BCGControlBar имеет правильный параметр DWORD_PTR. Однако факт остается фактом. Ошибка есть во вполне реальном коде и компилятор ее не обнаружит.
Что делать? Использовать PVS-Studio. Ведь наш анализатор с момента своего создания умеет находить такие ошибки, а справочная система содержит подробный пример (смотрите описание ошибки V301).
0