У меня есть некоторый код C, который анализирует упакованные / неупакованные двоичные данные, поступающие из сети.
Этот код был / работает нормально под Intel / x86, но когда я компилировал его под ARM, он часто зависал.
Виновником, как вы могли догадаться, были невыровненные указатели - в частности, код синтаксического анализа будет делать такие сомнительные вещи, как это:
uint8_t buf[2048];
[... code to read some data into buf...]
int32_t nextWord = *((int32_t *) &buf[5]); // misaligned access -- can crash under ARM!
... очевидно, что он не будет летать на ARM-земле, поэтому я изменил его так, чтобы он выглядел так:
uint8_t buf[2048];
[... code to read some data into buf...]
int32_t * pNextWord = (int32_t *) &buf[5];
int32 nextWord;
memcpy(&nextWord, pNextWord, sizeof(nextWord)); // slower but ARM-safe
Мой вопрос (с точки зрения юриста по языку) таков: хорошо ли определен мой "ARM-фиксированный" подход в правилах языка C?
Меня беспокоит то, что, возможно, даже просто иметь неправильный указатель int32_t может быть достаточно для вызова неопределенного поведения, даже если я никогда не разыменовываю его напрямую. (Если моя проблема верна, думаю, я мог бы решить эту проблему, изменив тип pNextWord
с (const int32_t *)
на (const char *)
, но я бы предпочел этого не делать, если это на самом деле не нужно, поскольку это значит делать ручную арифметику с указателем шага)