64-битный

Коллекция примеров 64-битных ошибок в реальных программах

Статья представляет собой наиболее полную коллекцию примеров 64-битных ошибок на языках Си и Си++. Статья ориентирована на разработчиков Windows-приложений, использующих Visual C++, но будет полезна и более широкой аудитории.
  • Си++
  • 64-битный
  • 64-бита
  • ошибки
  • Си
  • Уроки разработки 64-битных приложений на языке Си/Си++

    Мы регулярно пишем статьи посвященные разработке и тестированию 64-битных программ на языке Си/Си++. Каждая из статей представляет взгляд на задачу разработки 64-битных программ с разных точек зрения. Но существенная часть информации в них повторяется, так как необходимо знакомить читателя с проблематикой и вводить различные определения. Это, к сожалению, делает чтение подборки статей скучным занятием и соответственно не позволяет всесторонне изучить вопросы разработки 64-битных приложений.

    Проблемы 64-битного кода в реальных программах: qsort

    Продолжаем цикл рассказов о 64-битных ошибках, обнаруживаемых в реальных приложениях. Время идет, потребности в потребляемой памяти растут и пришел момент, когда кто-то решил отсортировать массив, состоящий более чем из 2^31 элементов. Для этого он решил воспользоваться функцией qsort, реализованной OpenBSD 4.5. Результатом стало обнаружение новой 64-битной ошибки.

    Оптимизация в мире 64-битных ошибок

    В предыдущей записи блога я обещал рассказать, почему сложно демонстрировать 64-битные ошибки на простых примерах. Разговор касался operator[] и я говорил, что в простых случаях может работать даже явно некорректный код. Сейчас я приведу такой пример:

    Тонкость с виртуальными функциями

    Решил записать один момент, связанный с виртуальными функциями, а то боюсь, что потом его забуду и случайно вновь вернусь к этому вопросу. :)

    В анализаторе Viva64 есть диагностика ошибок, возникающих в 64-битном коде, когда у виртуальных функций изменяется тип аргумента. Подробнее это описано в документации к продукту здесь: V301.

    Вот пример кода, где анализатор выдаст эти предупреждения:
    class A
    
    {
    
    public:
    
      virtual int x(unsigned) { return 1; }
    

    Почему A + B != A - (-B)

    Разрабатывая анализатор Viva64, предназначенный для поиска 64-битных ошибок, я иногда сталкиваюсь с интересными моментами поведения кода. Хочу показать один пример, который с практической точки зрения не очень интересен, но может быть полезен для понимания более сложных случаев.
    char *A = "123456789";
    
    unsigned B = 1;
    
    char *X = A + B; // X: "23456789"
    
    char *Y = A - (-B); // Y: <Bad Ptr>

    Проблемы 64-битного кода в реальных программах: изменение типа указателя

    Явные приведения типа часто маскируют ошибки, связанные с изменением типа указателя. Одной из таких ошибок является превращение указателя на 32-битные объекты в указатель на 64-битные объекты. Рассмотрим пример, присланный пользователями нашего инструмента PVS-Studio (Viva64). Ошибка проявляет себя после переноса кода на 64-битную версию Windows:
    void ProcessTime(long * pTime)
    
    {
    
      time((time_t *)pTime);
    
    }

    Красивая 64-битная ошибка на языке Си

    В языке Си можно использовать функции без их предварительного объявления. Обращаю внимание, что речь идет именно о языке Си, а не Си++. Конечно, данная возможность опасна. Рассмотрим связанный с ней интересный пример 64-битной ошибки. Ниже приведен корректный код, который выделяет и использует три массива размером 1 гигабайт каждый:
    #include < stdlib.h >
    
    
    void test()
    
    {
    
      const size_t Gbyte = 1024 * 1024 * 1024;
    
      size_t i;
    
      char *Pointers[3];
    
    
      // Allocate
    
      for (i = 0; i != 3; ++i)
    
        Pointers[i] = (char *)malloc(Gbyte);
    
    
      // Use
    
    Subscribe to 64-битный