Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 访问.rodata节中的特定数据时,应用程序崩溃_C_Gcc_Arm_Embedded - Fatal编程技术网

C 访问.rodata节中的特定数据时,应用程序崩溃

C 访问.rodata节中的特定数据时,应用程序崩溃,c,gcc,arm,embedded,C,Gcc,Arm,Embedded,我不得不完全重新表述这个问题及其标题,因为我最初的分析结果是错误的(感谢所有的提示和建议!)。问题的旧标题是: GCC-O3将二进制文件弄乱并产生数据垃圾 事实证明,这与优化级别无关,我也不确定数据是否是垃圾 总之,这些是我正在使用的SDK代码的相关片段。显然,我不能在这里发布整个SDK代码 首先,我有两个常数: static const usb_device_controller_interface_struct_t s_UsbDeviceEhciInterface = { USB_D

我不得不完全重新表述这个问题及其标题,因为我最初的分析结果是错误的(感谢所有的提示和建议!)。问题的旧标题是:

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};

在我的main.c中,似乎不相关,有以下片段:

if (kStatus_USB_Success != error)
{
    usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
if (kStatus_USB_Success != error)
{
    usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
现在,如果我使用
-O3
编译,应用程序在访问
s_-UsbDeviceEhciInterface
时崩溃,使用
-O0
则应用程序在访问
s_-usbdevicelclasseinterfacemap
时崩溃

这两次似乎都涉及到第三个代码段

对于
-O3
,反汇编中的数据对于
s_usbdeviceehcii接口来说如下所示:

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!...
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                                !...
对于
-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
重述一下:当从main.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!");
}
if (kStatus_USB_Success != error)
{
    usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
现在,访问
s_usbdeviceehcii界面
会使应用程序崩溃。查看反汇编文件,我发现以下内容:

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!...
这仅在我使用
-O3
优化时发生。当我切换到
-O0
时,一切似乎又恢复了正常

这种情况是如何发生的?在仍然使用
-O3
的情况下,有没有办法防止这种情况发生


编辑:我刚刚意识到它也发生在
-O0
中,只是在数据的另一部分。也许我弄糟了我的链接器脚本?

注意:这不是对崩溃的解释,而是试图解释假定的数据垃圾

您的反汇编似乎是从最终的可执行文件进行的。在该文件中,收集所有常量并将其附加到
rodata
部分。静态和常量结构
s_UsbDeviceEhciInterface
显然是只读数据,正如您在它后面找到的字符串文字一样

两者的区别在于前者有一个用户定义的名称,
s_UsbDeviceEhciInterface
,后者没有。这就是为什么反汇编将名称显示为起始标签,但不显示字符串的起始标签

您可以生成一个映射文件(链接器的选项
-map
),并查看多个对象及其位置

因此,no
-O3
不会产生数据垃圾

由于您发现
-O0
也会导致崩溃,因此需要从另一个方向进行调查。考虑部分溢出、悬空指针、未初始化变量等等。将所有警告级别提高到最大值

注意:这不是对崩溃的解释,而是试图解释假定的数据垃圾

您的反汇编似乎是从最终的可执行文件进行的。在该文件中,收集所有常量并将其附加到
rodata
部分。静态和常量结构
s_UsbDeviceEhciInterface
显然是只读数据,正如您在它后面找到的字符串文字一样

两者的区别在于前者有一个用户定义的名称,
s_UsbDeviceEhciInterface
,后者没有。这就是为什么反汇编将名称显示为起始标签,但不显示字符串的起始标签

您可以生成一个映射文件(链接器的选项
-map
),并查看多个对象及其位置

因此,no
-O3
不会产生数据垃圾


由于您发现
-O0
也会导致崩溃,因此需要从另一个方向进行调查。考虑部分溢出、悬空指针、未初始化变量等等。将所有警告级别提高到最大值

请尝试获取代码的反汇编输出,而不是查看原始十六进制转储。这不可能帮助您,因为您只提供了代码的一小部分。毫无疑问,您有一个代码错误,它不会为-O0显示,而只为-O3显示。发布完整的代码示例…打开编译器警告。GCC可能正在消除一个死代码路径。我刚刚意识到-O0也会发生这种情况,只是在另一个地方。我将尝试打开我的编译器警告,谢谢@JL2210@Someprogrammerdude:原始十六进制转储是数据对象,而不是代码。请尝试获取代码的反汇编输出,而不是查看原始十六进制转储。由于您只提供了代码的一小部分,因此无法为您提供帮助。毫无疑问,您有一个代码错误,它不会为-O0显示,而只为-O3显示。发布完整的代码示例…打开编译器警告。GCC可能正在消除一个死代码路径。我刚刚意识到-O0也会发生这种情况,只是在另一个地方。我将尝试打开我的编译器警告,谢谢@JL2210@Someprogrammerdude:原始十六进制转储文件是数据对象,不是代码。感谢您的解释,我将查看映射文件并提高所有警告级别。我发现有趣的是,对于
-O0
来说,同样的事情发生在另一个常数上。不过,您是对的,对我来说,它可能看起来像垃圾,因为其中一个数据结构没有用户定义的名称。不管怎样,我会继续调查的。可能是某种溢出。感谢您的解释,我将查看地图文件并提高所有警告级别。我觉得很有趣
000042b4 <s_UsbDeviceEhciInterface>:
    42b4:   00000479 00000b0d 00000b49 00000b55     y.......I...U...
    42c4:   00000b5d 00000d35                       ]...5...