Сложность чтения нестабильной памятиC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Сложность чтения нестабильной памяти

Сообщение Anonymous »

У меня есть код, который работал хорошо при составлении с GCC, но не работает правильно при составлении с Clang. Я отслеживал проблему до чтения нестабильной памяти (на микроконтроллере). Я обнаружил, что вступил в сборку, что память, связанная с PMA_ADDRESS , читается в регистр, но значения, установленные в регистре, никогда не используются. Таким образом, harder_setup_packet никогда не называется предположительно, потому что оптимизатор определил, что буфер никогда не изменится. Сделав Buffer_out в изменчивую uint8_t*, код работает правильно. Но я не понимаю, почему в этом случае это должно быть нестабильным. Я бы подумал, что одного волатильного будет достаточно, чтобы убедить компилятора, что буфер стоит посмотреть. Мне интересно, какова моя логическая ошибка в следующем коде: < /p>

Код: Выделить всё

void read_pma(uint8_t byte_count, volatile uint16_t * pma_address, uint8_t *buffer_out) {
int count_received_16 = (byte_count + 1) >> 1;
for(int i=0; ibuffer[0].EP_RX, buffer);
handle_setup_packet(reinterpret_cast(buffer));
}
< /code>

 Обновления < /h2>
Я добавляю дополнительную информацию для решения комментариев. Из предложений в комментариях я узнал больше о строгих псевдониме и нашел то, что я считаю основной проблемой. Компилятор Clang 20.1.0 предоставлен ARM: https://github.com/arm/arm-toolchain с опциями -target = armv7m-none-eabi -o3 -flto 
. Сгенерированная сборка довольно большая из-за развертывания петли, но, как правило, существует ряд разделов, подобных ниже, где он загружает многократное местоположение памяти PMA_ADDRESS и неоднократно пишет в реестр царапин.

Код: Выделить всё

;         ((uint16_t *) buffer_out)[i] = pma_address[i];
10000776: f835 3c1e     ldrh    r3, [r5, #-30]
1000077a: f835 3c1c     ldrh    r3, [r5, #-28]
1000077e: f835 3c1a     ldrh    r3, [r5, #-26]
10000782: f835 3c18     ldrh    r3, [r5, #-24]
10000786: f835 3c16     ldrh    r3, [r5, #-22]
1000078a: f835 3c14     ldrh    r3, [r5, #-20]
< /code>
Я нашел несколько нескольких способов, которыми я могу заставить его генерировать предполагаемую сборку ниже: < /p>
;         ((uint16_t *) buffer_out)[i] = pma_address[i];
8004370: 885f          ldrh    r7, [r3, #0x2]
8004372: eb00 0144     add.w   r1, r0, r4, lsl #1
8004376: f8a1 704d     strh.w  r7, [r1, #0x4d]
800437a: eb08 0744     add.w   r7, r8, r4, lsl #1
800437e: f8b7 20a2     ldrh.w  r2, [r7, #0xa2]
;     for(int i=0; i
Где сборка загружает и хранит информацию, полученную от PMA_ADDRESS. Решения, которые я обнаружил (без добавления летучих), которые приводят к правильному эксплуатационной программе, -это 1) компиляция без -flto 
, 2) компиляция с -фно -стрип -aliasing и 3) изменить код для решения нарушений псевдонима.

Код: Выделить всё

void read_pma(uint8_t byte_count, volatile uint16_t * pma_address, uint8_t *buffer_out) {
int count_received_16 = (byte_count + 1) >> 1;
for(int i=0; i> 8) & 0xFF;
}
}

fun() {
read_pma(byte_count, USBPMA->buffer[0].EP_RX, buffer);
usb_control_request ctrl_req {};
std::memcpy(&ctrl_req, buffer, sizeof(usb_control_request));
handle_setup_packet(&ctrl_req);
}

< /code>
Я попробовал, но не мог создать версию этого кода в исследователе Combiler Godbolt и мог бы получить непреднамеренное поведение только в контексте полной программы. Главное, что удивило меня в отладке, заключается в том, что с LTO на компиляторе может полностью игнорировать функцию harder_setup_packet 
из -за нарушения псевдонима. Я проверил это, поместив неверный код в этой функции ASM ("Invalid_op;"); в этом коде, которые не создавали ошибок при составлении в режиме LTO.

Подробнее здесь: https://stackoverflow.com/questions/797 ... ile-memory
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»