Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
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
Ваше сообщение отправлено.

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


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам

Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12

>
>
>
V220. Suspicious sequence of types cast…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V220. Suspicious sequence of types castings: memsize -> 32-bit integer -> memsize.

05 Мар 2015

Предупреждение информирует о наличии странной последовательности приведений типа. Memsize-тип явно приводится к 32-битному целочисленному типу. А затем тут же вновь явно или неявно приводится к memsize-типу. Такая последовательность приведений приводит к потере значений старших бит. Как правило, это свидетельствует о наличии серьезной ошибки.

Рассмотрим пример:

char *p1;
char *p2;
ptrdiff_t n;
...
n = int(p1 - p2);

Здесь присутствует лишнее приведение к типу 'int'. Оно не нужно и может послужить причиной сбоя, если в 64-битной программе указатели p1 и p2 будут отстоять друг от друга больше чем на INT_MAX элементов.

Корректный вариант кода:

char *p1;
char *p2;
ptrdiff_t n;
...
n = p1 - p2;

Рассмотрим другой пример:

BOOL SetItemData(int nItem, DWORD_PTR dwData);
...
CItemData *pData = new CItemData;
...
CListCtrl::SetItemData(nItem, (DWORD)pData);

Этот код приведёт к ошибке, если объект типа CItemData будет создан за пределами четырех младших гигабайт памяти. Корректный вариант кода:

BOOL SetItemData(int nItem, DWORD_PTR dwData);
...
CItemData *pData = new CItemData;
...
CListCtrl::SetItemData(nItem, (DWORD_PTR)pData);

Следует учитывать, что анализатор не выдаёт предупреждение, если конвертации подвергается такие типы данных, как HANDLE, HWND, HCURSOR и так далее. Хотя, по сути, это указатели (void *), их значения всегда вмещаются в младшие 32-бита. Это сделано специально, чтобы эти дескрипторы (handles) можно было передавать между 32-битными и 64-битными процессами. Подробнее: Как корректно привести указатель к int в 64-битной программе?

Рассмотрим пример:

typedef void * HANDLE;
HANDLE GetHandle(DWORD nStdHandle);
int _open_osfhandle(intptr_t _OSFileHandle, int _Flags);
....
int fh = _open_osfhandle((int)GetHandle(sh), 0);

Здесь имеет место преобразование вида:

HANDLE -> int -> intptr_t

Т.е. вначале указатель превращается в 32-битный тип 'int', а замет расширяется до 'intptr_t'. Это не очень красиво. Лучше было бы написать "(intptr_t)GetHandle(STD_OUTPUT_HANDLE)". Однако, никакой ошибки здесь и нет, так как значения типа HANDLE помещаются в 'int'. Поэтому анализатор промолчит.

Если будет написано:

int fh = _open_osfhandle((unsigned)GetHandle(sh), 0);

То анализатор выдаст предупреждение. Смешивание знаковых и беззнаковых типов всё портит. Представим, что GetHandle() вернёт INVALID_HANDLE_VALUE. Это значение задано в системных заголовочных файлах следующим образом.

#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)

Посмотрим, что получитcя при преобразовании (intptr_t)(unsigned)((HANDLE)(LONG_PTR)-1):

-1 -> 0xffffffffffffffff -> HANDLE -> 0xffffffffu -> 0x00000000fffffffff

Значение -1 превратилось в 4294967295. Это может быть не учтено программистом и программа может работать некорректно, если функция GetHandle() вернёт INVALID_HANDLE_VALUE. Поэтому, для второго случая анализатор выдаст предупреждение.