Мне пришлось перефразировать этот вопрос и его название полностью, потому что мой первоначальный анализ оказался неверным ( спасибо за все подсказки и предложения!) . Старый заголовок вопроса звучал так:
GCC -O3 портит двоичный файл и производит мусор данных
Как оказалось, он не имеет ничего общего с уровнями оптимизациии я не уверен, что данные также являются мусором.
В любом случае, это соответствующие фрагменты кода SDK, который я использую. Я не могу опубликовать весь код SDK здесь, очевидно.
Сначала у меня есть две константы:
static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl};
и
static const usb_device_class_map_t s_UsbDeviceClassInterfaceMap[] = {
{USB_DeviceCdcAcmInit, USB_DeviceCdcAcmDeinit, USB_DeviceCdcAcmEvent, kUSB_DeviceClassTypeCdc},
{(usb_device_class_init_call_t)NULL, (usb_device_class_deinit_call_t)NULL, (usb_device_class_event_callback_t)NULL,
(usb_device_class_type_t)0},
};
в моем main.c, по-видимомуне имеет отношения, есть этот фрагмент:
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
Теперь, , если я компилирую с -O3
, приложение вылетает при доступе к s_UsbDeviceEhciInterface
, с -O0
приложение вылетает при обращении к s_UsbDeviceClassInterfaceMap
.
Оба раза кажется, что задействован третий фрагмент кода.
С -O3
данные внутри разборки выглядят так для s_UsbDeviceEhciInterface
:
000066b4 <s_UsbDeviceEhciInterface>:
66b4: 00000479 0000145d 00001499 000014a5 y...]...........
66c4: 000014ad 00001685 4253556b 7665445f ........kUSB_Dev
66d4: 43656369 76456364 53746e65 6f437465 iceCdcEventSetCo
66e4: 6f72746e 6e694c6c 61745365 65206574 ntrolLineState e
66f4: 726f7272 00000021 rror!...
пока s_UsbDeviceClassInterfaceMap
, кажется, вообще не существует.
С -O0
данные внутри разборки выглядят так для s_UsbDeviceEhciInterface
:
00009164 <s_UsbDeviceEhciInterface>:
9164: 000018b5 00001999 00006ebb 00006eed .........n...n..
9174: 00001a21 00001c35 !...5...
и для s_UsbDeviceClassInterfaceMap
:
0000917c <s_UsbDeviceClassInterfaceMap>:
917c: 00007eb1 00007f49 00002985 00000002 .~..I....)......
...
919c: 00007071 4253556b 7665445f 43656369 qp..kUSB_DeviceC
91ac: 76456364 53746e65 6f437465 6f72746e dcEventSetContro
91bc: 6e694c6c 61745365 65206574 726f7272 lLineState error
91cc: ffff0021 !...
В файле карты мы оба раза видим данные main.c, следующие за const - как и предполагалось при разборке. Для -O3
:
.rodata.s_UsbDeviceEhciInterface
0x00000000000066b4 0x18 ./usb/device/source/usb_device_dci.o
.rodata.USB_DeviceCdcVcomCallback.str1.4
0x00000000000066cc 0x30 ./source/main.o
и для -O0
:
.rodata.s_UsbDeviceEhciInterface
0x0000000000009164 0x18 ./usb/device/source/usb_device_dci.o
.rodata.s_UsbDeviceClassInterfaceMap
0x000000000000917c 0x20 ./usb/device/class/usb_device_class.o
.rodata 0x000000000000919c 0x32 ./source/main.o
Напомним: приложение всегда аварийно завершает работу при обращении к константе, предшествующей константной строке, из основного.c
Я попытался запустить предупреждения компилятора, и я получил только некоторые неиспользуемые параметры в коде SDK.
Для полнотыради вот оригинальный вопрос:
УСТАРЕЛ (см. выше)
Итак, у меня есть этот код:
static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = {
USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend,
USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl};
и где-то еще, в другом файле, казалось бы, не связанном, у меня есть этот фрагмент:
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
Теперь доступ к s_UsbDeviceEhciInterface
приводит к сбою приложения. Просматривая файл дизассемблирования, я обнаружил следующее:
00006674 <s_UsbDeviceEhciInterface>:
6674: 00000479 0000145d 00001499 000014a5 y...]...........
6684: 000014ad 00001685 4253556b 7665445f ........kUSB_Dev
6694: 43656369 76456364 53746e65 6f437465 iceCdcEventSetCo
66a4: 6f72746e 6e694c6c 61745365 65206574 ntrolLineState e
66b4: 726f7272 00000021 rror!...
, представляющее собой комбинацию двух не связанных между собой частей кода!
Если удалить второй фрагмент кода, доступ к s_UsbDeviceEhciInterface
работаеточередной раз. В этом случае разборка выглядит следующим образом:
000042b4 <s_UsbDeviceEhciInterface>:
42b4: 00000479 00000b0d 00000b49 00000b55 y.......I...U...
42c4: 00000b5d 00000d35 ]...5...
Это происходит только тогда, когда я использую оптимизацию -O3
. Когда я переключаюсь на -O0
, все снова кажется нормальным.
Как это происходит и есть ли способ предотвратить это, все еще используя -O3
?
РЕДАКТИРОВАТЬ: я только что понял, что это происходитс -O0
также, просто в другой части данных. Может я испортил свой скрипт компоновщика?