|
|
|||
![]() PVS-Studio, статический анализатор кода для 64-битного и параллельного программирования на Си/Си++
|
|||
![]() ![]() ![]() ![]() ![]()
02.09.2010
Щупаем новый Intel Parallel Studio XE 2011 beta Вот, наконец, добрался попробовать Си++ компилятор, входящий в состав Intel Parallel Studio XE 2011 beta.»
30.08.2010
Пять дней на исправление ошибки в два символа, или миф о всемогущих технологиях при разработке программ В этом блоге нередко можно почитать о том, как тот или иной программный инструмент, или технология разработки программ помогает делать меньше ошибок, быстрее их находить, легче исправлять.»
30.08.2010
Д'Артаньян и интернет, или работа над проблемой битых ссылок Господа, хватит уже рассматривать ссылки исключительно в контексте их количества, купли/продажи и считать PR сайта, где они расположены.» ![]()
22.07.2010
Использование PVS-Studio вместе с системами continuous integration В статье показаны приемы организации работы анализатора кода PVS-Studio вместе с системами непрерывной интеграции (continuous integration).»
06.07.2010
Сравнение возможностей PVS-Studio и Visual Studio 2010 по выявлению дефектов в 64-битных программах В статье сравниваются три механизма анализа кода с точки зрения выявления 64-битных ошибок: компилятор Visual C++2010, компонент Code Analysis for C/C++ входящий в состав Visual Studio 2010 Premium/Ultimate и анализатор Viva64 входящий в состав PVS-Studio 3.60. »
29.06.2010
Коллекция примеров 64-битных ошибок в реальных программах
Статья представляет собой наиболее полную коллекцию примеров 64-битных ошибок на языках Си и Си++. » ![]() |
64-битные уроки![]() Урок 15. Паттерн 7. Упаковка указателейБольшое количество ошибок при миграции на 64-битные системы связано с изменением соотношения между размером указателя и размером обычных целых. В среде с моделью данных ILP32 обычные целые и указатели имеют одинаковый размер. К сожалению, 32-битный код повсеместно опирается на это предположение. Указатели часто приводятся к int, unsigned, long, DWORD и другим неподходящим типам. Следует четко помнить, что для целочисленного представления указателей следует использовать только memsize типы. Предпочтение, на наш взгляд, следует отдавать типу uintptr_t, так как он лучше выражает намерения и делает код более переносимым, предохраняя его от изменений в будущем. Рассмотрим два небольших примера. 1) char *p; p = (char *) ((int)p & PAGEOFFSET); 2) DWORD tmp = (DWORD)malloc(ArraySize); ... int *ptr = (int *)tmp; Оба примера не учитывают, что размер указателя может отличаться от 32 бит. Используется явное приведение типа, отбрасывающее старшие биты в указателе, что является явной ошибкой на 64-битной системе. Исправленные варианты, использующие для упаковки указателей целочисленные memsize типы (intptr_t и DWORD_PTR), приведены ниже: 1) char *p; p = (char *) ((intptr_t)p & PAGEOFFSET); 2) DWORD_PTR tmp = (DWORD_PTR)malloc(ArraySize); ... int *ptr = (int *)tmp; Опасность двух рассмотренных примеров в том, что сбой в программе может быть обнаружен спустя очень большой промежуток времени. Программа может совершенно корректно работать с небольшим объемом данных на 64-битной системе, пока обрабатываемые адреса находятся в пространстве первых четырех гигабайт памяти. А затем, при запуске программы на больших производственных задачах, произойдет выделение памяти за пределами этой области. Рассмотренный в примерах код, обрабатывая указатель на объект вне данной области, приведет к неопределенному поведению программы. Следующий приведенный код не будет таиться и проявит себя при первом выполнении: void GetBufferAddr(void **retPtr) {
...
// Access violation on 64-bit system
*retPtr = p;
}
unsigned bufAddress;
GetBufferAddr((void **)&bufAddress);
Исправление также заключается в выборе типа, способного вмещать в себя указатель. size_t bufAddress; GetBufferAddr((void **)&bufAddress); //OK Бывают ситуации, когда упаковка указателя в 32-битный тип просто необходима. В основном такие ситуации возникают при необходимости работы со старыми API функциями. Для таких случаев следует прибегнуть к специальным функциям, таким как LongToIntPtr, PtrToUlong и так далее. Резюмируя, хочется заметить, что плохим стилем будет упаковка указателя в типы, всегда равные 64 битам. Показанный ниже код вновь придется исправлять с приходом 128-битных систем: PVOID p; // Bad style. The 128-bit time will come. __int64 n = __int64(p); p = PVOID(n); Поговаривают, что уже сегодня разработчики Microsoft Research работают над проектом по обеспечению совместимости ядер Windows 8 и Windows 9 с 128-битной архитектурой. Так что пишите хороший код сразу. ДиагностикаУпаковка указателя в 32-битные типы диагностируется инструментом PVS-Studio посредством диагностических сообщений V114 и V202. Следует заметить, что простые ошибки приведения указателей к 32-битным типам хорошо диагностируются компилятором Visual C++. Например, компилятор предупредит об ошибке в коде, рассмотренном выше: char *p; p = (char *) ((int)p & PAGEOFFSET); Visual C++ выдаст предупреждение "warning C4311: 'type cast' : pointer truncation from 'char *' to 'int'". Однако, пример c GetBufferAddr уже не вызовет у Visual C++ подозрений. Таким образом, PVS-Studio позволяет быть более уверенным в отсутствии таких ошибок, чем диагностика Visual C++. Рассмотрим еще один важный момент, связанный с использованием анализатора PVS-Studio. Хотя некоторые из рассматриваемых в уроках ошибок могут быть обнаружены с использованием предупреждений Visual C++, это не всегда получается осуществить на практике. В больших и старых проектах, содержащих вдобавок большие сторонние библиотеки, часто отключены многие предупреждения, что снижает вероятность обнаружения 64-битных ошибок. Включать эти предупреждения бывает крайне нежелательно. Предупреждений будет много, но только часть из них может помочь выявить ошибки 64-битности. Остальные предупреждения не будут относиться к делу, и скорее будут свидетельствовать о неаккуратности кода, чем о потенциальных 64-битных проблемах. В описанной ситуации PVS-Studio окажет неоценимую услугу. Он выделит в коде только те потенциальные ошибки, которые относятся к вопросам переноса проекта на 64-битную архитектуру. Авторы курса: Андрей Карпов (karpov@viva64.com), Евгений Рыжков (evg@viva64.com). Правообладателем курса "Уроки разработки 64-битных приложений на языке Си/Си++" является ООО "Системы программной верификации". Компания занимается разработкой программного обеспечения в области анализа исходного кода программ. Сайт компании: http://www.viva64.com. Контактная информация: e-mail: support@viva64.com, 300027, г. Тула, а/я 1800. | ||