статическая переменная uint8_t меняется на неверное значение при использовании + = на Mac - PullRequest
1 голос
/ 22 апреля 2019

У меня сегодня был коллега, задающий мне вопрос относительно его кода, на который я не смог ответить.Он пишет модульный тест на C на Mac, который использует статическую переменную uint8_t (инициализированную в 0) для хранения текущей позиции чтения из буфера тестирования через вызовы, казалось бы, простой функции чтения в тестовом коде.Арифметика была следующей:

    /*Fails to add correctly on the third iteration of the loop \*/
    /* static uint8_t currentReadPosition = 0; \*/
    /* uint32_t tempreadamount \*/
    currentReadPosition += tempreadamount;

Я запустил код в Linux, и значения изменились правильно (в соответствии с кодом), поэтому проблема, похоже, специфична для платформы Mac.Я попросил его изменить значение с uint8_t на uint32_t на догадке, и когда он перезапустил тест, он запустился правильно.

    /* Works correctly \*/
    /* static uint32_t currentReadPosition \*/
    /* uint32_t tempreadamount \*/
    currentReadPosition += tempreadamount;

Он использует memcpy () в функции, но назначение записи -вне области действия функции (она передается в функцию чтения в качестве параметра).Я не видел никаких проблем с ним, используя неправильный указатель назначения или что-то в этом роде.

Я понятия не имею, почему работает uint32_t, а uint8_t - на Mac, но uint8_t - на Linux.Кто-нибудь знает, что здесь происходит?

Спасибо.

uint8_t resetcurrptr = 0;
int readfunc_cb_test( uint8_t* OutBuf, uint32_t NumBytes )
{
static uint8_t currentReadPosition = 0;

  if( resetcurrptr )
  {
    currentReadPosition = 0;
  }

  uint32_t readamt = NumBytes;
  if( NumBytes > ( ( sizeof(TestRequestPacket) / sizeof(TestRequestPacket[0] ) ) - currentReadPosition) )
  {
    readamt = ( sizeof(TestRequestPacket) / sizeof(TestRequestPacket[0]) - currentReadPosition );
  }

  memcpy( OutBuf, &TestRequestPacket[currentReadPosition], readamt );

  currentReadPosition += readamt;

  return readamt;
}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2019

Итак, я раскрыл тайну этим утром ...

Мой коллега использует LLDB для отладки на Mac вместо GDB. Когда он отлаживает это с помощью LLDB и значение достигает 8, отладчик показывает «\ b». Оказывается, это не 0xB, а '\ b' ... код ASCII для BACKSPACE, который имеет целочисленное значение 8.

Я понял это только после того, как снова увидел поведение, когда мы смотрели, как его структура (казалось бы) отступает до 11, когда она вообще не должна была заполняться ..

Спасибо всем за ответы.

1 голос
/ 22 апреля 2019

Добавление uint32 к uint8 может привести к переполнению (8 бит переворачиваются и начинаются с 0, если результат больше 255). Если в вашем случае происходит переполнение, это может быть объяснением.

С http://www.cs.utah.edu/~regehr/papers/overflow12.pdf: "Многие целочисленные переполнения без знака в C и C ++ хорошо определены, но непереносимы"

Таким образом, изменение, которое вы упоминаете в currentReadPosition, чтобы быть uint32, является правильным решением. Это делает код более переносимым и в целом рекомендуется избегать переполнений без необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...