Важная информация
Показано с 1 по 1 из 1

Тема: И на старуху бываете проруха...

  1. #1 И на старуху бывает проруха... 
    Разбирающийся
    Регистрация
    06.09.2012
    Адрес
    MPLS/MN USA
    Сообщений
    31
    Сказал(а) спасибо
    0
    Поблагодарили 1 раз в 1 сообщении
    Записей в блоге
    1
    Давно не писал код на чистом Си. Соотв и прямое использование массивов через указатель тоже.
    Напоролся на логический баг. Хочу поделиться, потому-что знаю, что новички часто, сталкиваясь
    с ним, забивают на работу с указателями вообще.

    Допустим, в некоторую функцию передается константный указатель на массив и соотв размер массива.

    Код :
    void SomeFunction( const char* buff, size_t size )
    {
    ...
    }

    и где-то в теле цикла нам нужно пройтись по всему массиву, для того, чтобы произвести какое-то
    действие с ним. Ну допустим добавить ко всем элементам единичку. Обычно я создаю указатель
    того же типа что и массив и инициализирую его указателем на массив. И далее работаю с массивом
    через него. И достаточно часто, особенно по началу своей практики, я совершал типовую логическую
    ошибку. Вот пример с этой ошибкой:

    Код :
    void SomeFunction( const char* buff, size_t size)
    {
    char*p = buff;
     
    while( p < ( p+size ) )  // << ----- проблема кроется здесь
    (*p++)++;
    }

    Суть проблемы в том, что такой цикл остановится наверняка не сразу и гарантирован крах
    программы с ошибкой записи/чтения. Этот вариант чаще всего возникает интуитивно и в
    этом случае, на самом деле, проблема в том, что выражение ( p+size ) не решение... потому-что
    оно не статично. Оно изменяется с ростом указателя p; Так что вот "правильное" решение:

    Код :
    void SomeFunction( const char* buff, size_t size)
    {
    char* p = buff;
    char* end = buff+size;
     
    while( p < end )  // << -- всё правильно! теперь выражение end статично! инвариант конечен.
    (*p++)++;
    }

    P.S. Но есть ньюанс. Некоторые компиляторы в цикле for позволяют использовать ( p+size ).
    связывая его только один раз, при входе в цикл. Но у некоторых это не сработает. Поэтому
    рекомендую не полагаться на эту недодумку со стороны разработчиков компиляторов, и каждый
    раз самому статически связывать конечное условие.

    Удачи! Всем поменьше нелепых, занудных багов!
    Последний раз редактировалось handrix; 11.09.2012 в 10:53.
    Ответить с цитированием  
     

Информация о теме
Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права
  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •