metrica
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

Вебинар: Трудности при интеграции SAST, как с ними справляться - 04.04

>
>
>
Урок 12. Паттерн 4. Виртуальные функции

Урок 12. Паттерн 4. Виртуальные функции

24 Янв 2012

Бывают ошибки, в которых, в общем-то, никто не виноват, но они от этого не перестают быть ошибками. Представьте, что давным-давно (в Visual Studio 6.0) был разработан проект, в котором присутствует класс CSampleApp, являющийся наследником от CWinApp. В базовом классе есть виртуальная функция WinHelp. Наследник перекрывает эту функцию и выполняет необходимые действия. Визуально это представлено на рисунке 1.

12_Pattern_04_Virtual_functions_ru/image1.png

Рисунок 1 - Работоспособный корректный код, который создан в Visual Studio 6.0

Затем проект переносится на Visual Studio 2005, где прототип функции WinHelp изменился, но этого никто не замечает, так как в 32-битном режиме типы DWORD и DWORD_PTR совпадают и программа продолжает корректно работать (рисунок 2).

12_Pattern_04_Virtual_functions_ru/image3.png

Рисунок 2 - Не корректный, но работоспособный 32-битный код

Ошибка ждет, чтобы проявить себя в 64-битной системе, где размер типов DWORD и DWORD_PTR различен (рисунок 3). Получается, что в 64-битном режиме классы содержат две РАЗНЫЕ функции WinHelp, что естественно некорректно. Учтите, что подобные ловушки могут скрываться не только в MFC, где часть функций изменили типы своих аргументов, но и в коде ваших приложений и сторонних библиотек.

12_Pattern_04_Virtual_functions_ru/image5.png

Рисунок 3 - Ошибка проявляет себя в 64-битном коде

Рассмотрим данную ошибку на реальном примере. Есть прекрасная библиотека компонентов BCGControlBar. Наверняка вы про нее слышали, поскольку компоненты компании BCGSoft Ltd включены в Microsoft Visual Studio 2008 Feature Pack. Так вот, если скачать ознакомительную версию этой библиотеки, установить ее и выполнить поиск слова "WinHelp" по .h-файлам... то мы увидим, что везде, где якобы перекрыта эта функция, используется параметр DWORD, вместо DWORD_PTR. А это означает, что справка в 64-битной системе в этих классах будет вести себя некорректно.

Почему подобная ошибка может до сих пор быть в коде такой известной библиотеки? Мы думаем, дело в том, что клиентам компании доступны исходные коды этой библиотеки и клиенты всегда могут поправить эти коды. Кроме того, в настоящее время функция WinHelp используется очень редко. Намного чаще используется HtmlHelp. А она-то в BCGControlBar имеет правильный параметр DWORD_PTR. Однако факт остается фактом. Ошибка есть в реальном коде и компилятор ее не обнаружит. Причем такие ошибки могут оставаться не выявленными годами.

Примечание. Статья писалась в октябре 2009 года, и, скорее всего, в следующих версиях эта ошибка будет исправлена, тем более что мы сообщили о ней разработчикам библиотеки.

Диагностика

Ошибки, связанные с виртуальными функциями в 64-битном коде, могут быть обнаружены статическим анализатором PVS-Studio. Анализатор предупредит об опасных виртуальных функциях диагностическим сообщением V301.

Виртуальная функция считается опасной, если:

  • Функция объявлена в базовом классе и в классе-потомке.
  • Типы аргументов функций не совпадают, но эквивалентны на 32-битной системе (например: unsigned, size_t) и не эквивалентны на 64-битной.

Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com).

Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com.