Обнаружить арифметику указателей из-за LARGEADDRESSAWARE - PullRequest
8 голосов
/ 16 июня 2010

Я бы хотел переключить свое приложение на LARGEADDRESSAWARE. Одной из проблем, требующих внимания, является арифметика указателей, поскольку разность указателей больше не может быть представлена ​​в виде знака 32b.

Есть ли способ, как автоматически найти все экземпляры вычитания указателя в большом проекте C ++?

Если нет, то есть ли какой-нибудь ручной или полуавтоматический метод «наименьших усилий», как этого добиться?

Ответы [ 5 ]

3 голосов
/ 16 июня 2010

PC-Lint может найти такую ​​проблему.

Посмотрите на http://gimpel -online.com / MsgRef.html , код ошибки 947:

Оператор вычитания применяется к указателям - выражение была найдена форма p - q, где p и q являются указателями. Это из особое значение в случаях, когда максимальный указатель может переполнить тип, который содержит различия указателя. Например, Предположим, что максимальный указатель составляет 3 гигабайта -1, и что Различия указателей представлены длинным, где максимальная длина составляет 2 гигабайта -1. Обратите внимание, что оба эти количества соответствуют в пределах 32-битного слова. Затем вычитая маленький указатель из очень большой указатель будет производить очевидное отрицательное значение в long, представляющий разность указателей. Наоборот, вычитание очень большого указателя из маленького указателя может привести к положительное количество.

1 голос
/ 16 июня 2010

Скомпилируйте код с 64-битным компилятором и включенным Wp64.

Поскольку указатели имеют ширину 64 бита, а int, long, DWORD и т. Д. Остаются 32-разрядными, вы получаете предупреждения за закорачивание ptrdiff_t в int32_t

0 голосов
/ 06 марта 2019

Сколько бы это ни стоило, я просмотрел Предупреждения компилятора Microsoft для VS2017 и искал все предупреждения, относящиеся к "подписанным", "усеченным" (усечению) и "конв" (преобразованию), были выше, чем уровень предупреждения 1. Затем я явно включил эти предупреждения для всех проектов в нашем решении с помощью таблицы. Чтобы включить определенные предупреждения, перейдите в раздел «C / C ++ / Командная строка / Дополнительные параметры» и добавьте их в формате / wL ####, где L - это уровень предупреждения, которому вы хотите назначить, а #### - это уровень. номер предупреждения.

Итак, я пришел к следующему списку:

/ w14365 / w14018 / w14146 / w14245 / w14092 / w14287 / w14308 / w14388 / w14389 / w14757 / w14807 / w14302 / w14305 / w14306 / w14307 / w14308 / w14309 / w14310 / w14311 / w14312 / w14051 / w14055 / w14152 / w14239 / w14223 / w14242 / w14243 / w14244 / w14254 / w14267 / w14333 / w14334 / w14367 / w14686 / w14826

Обратите внимание, что я использовал / w1, потому что наш глобальный уровень предупреждений уже упал до 1 (не судите меня, это наследие). Поэтому некоторые из этих предупреждений уже включены, если для уровня предупреждения по умолчанию установлено значение 3 или выше.

Это привело к появлению более 88000 предупреждений, большинство из которых касалось использования int вместо size_t в коде с использованием STL и преобразований, касающихся типов API Windows, таких как дескрипторы, WPARAM и UINT_PTR, и тому подобное. Я нашел только несколько предупреждений, связанных с фактической арифметикой указателей в сторонней библиотеке, но в контексте они выглядели нормально.

В любом случае, я подумал, что этот список связанных предупреждений может кому-то помочь.

Также используйте инструменты, описанные в этом ответе: https://stackoverflow.com/a/22745579/9635694

Другой вариант - запустить анализ встроенного кода в соответствии с CppCoreGuideLines . Перейдите в «Главное меню / Анализ / Настройка анализа кода / Для решения» и выберите «C ++ Core Check Raw Pointer Rules» для всех проектов, которые вы хотите проанализировать. Затем «Главное меню / Анализ / Выполнить анализ кода / Для решения». Остерегайтесь: изменяет ваши проекты, занимает много времени и может генерировать много предупреждений. Возможно, вы захотите сконцентрироваться на C26481 «Не использовать арифметику указателей» и, возможно, C26485 «Нет затухания между массивами и указателями».

0 голосов
/ 16 июня 2010

Поскольку наш код уже компилируется с GCC, я думаю, возможно, самый быстрый способ может быть:

  • построить GCC
  • создать пользовательскую модификацию GCC, чтобы она выводила предупреждение (или ошибку) при обнаружении вычитания указателя
  • построить проект и собрать все предупреждения о вычитании указателя

Вот схема изменений, которые необходимо внести в GCC для этого:

Добавьте ваши предупреждения в:

  • c-typeck.c (pointer_diff функция)
  • cp / typeck.c (pointer_diff функция).

Помимо непосредственного обнаружения вычитания указателя, еще одна вещь, которую нужно сделать, может обнаружить случаи, когда вы сначала преобразовываете указатели в целочисленные типы, а затем вычитаете их. Это может быть более сложным, в зависимости от того, как структурирован ваш код, в любом случае поиск по регулярному выражению (. intptr_t). -. * - (. * Intptr_t) сработал достаточно хорошо.

0 голосов
/ 16 июня 2010

Это проблема, только если у вас есть 2 указателя с разнесением более 2000 миллионов байтов (2 ГБ) Это означает, что вы:

  • либо имеют очень большие массивы (> 2 ГБ)
  • или вы вычитаете указатели, которые указывают на совершенно разные структуры

Так что поищите эти особые случаи.

Я думаю, что в большинстве случаев это не проблема.

...