Загрузка…





  • Сообщения   Поиск
  • Andrey Karpov19.11.2009 01:49   
    Найди ошибки. Пример 2.

    Предлагаю найти ошибки в новом примере кода. Данный код корректно выполняется в 32-битном режиме и аварийно завершаться после компиляции в 64-битном режиме.


    long GetInversely(const long *endPtr, unsigned i)
    {
      if (endPtr == NULL)
        throw i;
      return endPtr[1 - i];
    }
    
    long Example2()
    {
      long array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      unsigned size = sizeof(array) / 4;
      long *end = array + size - 1;
    
      long sum = 0;
      for(unsigned i = size; i > 0; i--)
      {
        sum += GetInversely(end, i);
      }
      return sum;
    }
    

     


    P.S. Просьба к гуру не спешить сразу дать ответы. :-)



    ialexander20.11.2009 00:23
    Рейтинг
     
    Re: Найди ошибки. Пример 2.

    endPtr[1 - i]
    Тип переменной i - unsigned int, 32 бита.
    Значит, значение выражение 1-i приводится к unsigned int. Получается очень большее положительное число, затем переводится к типу int, 32 бита в 32-битной версии и получаем в итоге небольшое отрицательное число, но в случае 64-битной версии, 32-битный unsigned конвертируется в 64-битный int. Оно дополняется нулевыми разрядами до 32 бит и остается большим положительным числом (знаковый разряд оказывается уже не знаковым).
    Других проблем я не заметил.


    Andrey Karpov20.11.2009 01:29
    Рейтинг
     
    Re: Найди ошибки. Пример 2.

    В рамках Win64 действительно пример содержит только одну ошибку при вычислении индекса: endPtr[1 - i]. Но если посмотреть более широко, то есть еще одна ошибка, которая проявит себя на Linux системах. Это использование магического числа 4. В Linux, где используется модель данных LP64 тип long занимает в 64-битной программе не 4, а 8 байт.

    С учетом этих правок, данный код можно поправить так:

    long GetInversely(const long *endPtr, ptrdiff_t i)
    {
      if (endPtr == NULL)
        throw i;
      return endPtr[1 - i];
    }
    
    long Example2()
    {
      long array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      unsigned size = sizeof(array) / sizeof(long);
      long *end = array + size - 1;
    
      long sum = 0;
      for(ptrdiff_t i = size; i > 0; i--)
      {
        sum += GetInversely(end, i);
      }
      return sum;
    }
    

     

    Есть ли еще какие-то потенциальные недочеты?



    Andrey Karpov22.11.2009 23:05
    Рейтинг
     
    Re: Найди ошибки. Пример 2.

    Поскольку больше замечаний к коду нет, то есть у меня. :)

    Исправленный вариант кода приведет к тому, что изменится поведение при генерации исключения (throw i;). Использовать неспециализированные типы для генерации исключений является в любом случае плохим стилем. В рассматриваемом коде может привести к реальной ошибке. Если где-то в другом месте исключением обрабатывалось как catch(int value) {}, то после исправления типа переменной i на ptrdiff_t обработчик будет пропущен и произойдет изменение логики работы программы.

    Подробнее: V115. Memsize type used for throw, V116. Memsize type used for catch.



Быстрый переход:  

Статистика форумов Intel Software Network

424 пользователей 501 тем и 5,399 сообщений.

За последние 24 часа появилось 0 новых тем 0 новых сообщений и 0 новых пользователей.

Самая популярная тема за последние 3 дня Конкурс футболок для участников ISN 2012 Больше всего ответов отправлено на сообщение Вот пример распо Наибольшее количество просмотров у сообщения 0

Приветствуем нового пользователя claudepi


Пожалуйста, обратитесь к странице Уведомление об оптимизации для более подробной информации относительно производительности и оптимизации в программных продуктах компании Intel.