请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号: RM57L843
当通过包含的指定初始化值初始化具有匿名位字段填充的结构时 运行时间 值、 -O0 处的编译器 无法对匿名填充位进行零初始化。 生成的代码读取未初始化的栈字节、并且只修改命名位字段、从而保留匿名填充栈上的任何垃圾。
错误 不 在以下情况下发生:
-初始化值是一个编译时常量(例如,true)
-填充位字段被赋予一个名称(例如, unsigned int reserved : 7)
-优化是 -O1 或更高(编译器采用不同的代码生成路径)
使用 TI Arm Clang 编译器 4.0.3.LTS (tiarmclang 18.1.8) 编译以下程序时、会重现该问题:
#include <stdbool.h>
#include <stdint.h>
typedef struct {
bool field_a : 1; // bit 0
unsigned int : 7; // bits 1-7 (anonymous padding)
} __attribute__((packed)) packed_t;
typedef union {
packed_t s;
uint8_t byte;
} test_t;
/* At -O0, result.byte may contain garbage in bits 1-7.
* At -O1 or higher, result.byte is correct.
* Naming the padding (e.g., "unsigned int reserved : 7")
* also produces correct results at -O0.
*/
test_t make(bool val) {
test_t result = { .s.field_a = val };
return result;
}
编译命令:
tiarmclang -mcpu=cortex-r5 -mthumb -O0 -std=c17 -S anonimous_members_bug.c -o anonimous_members_bug_O0.s
tiarmclang -mcpu=cortex-r5 -mthumb -O1 -std=c17 -S anonimous_members_bug.c -o anonimous_members_bug_O1.s
为 make at -O0 生成的汇编代码会从堆栈中读取结果字节 先前已被写入 、则只修改位 0:
make:
sub sp, #4
strb.w r0, [sp, #2] @ save parameter
ldrb.w r0, [sp, #2] @ reload parameter
and r1, r0, #1 @ extract bit 0
ldrb.w r0, [sp, #3] @ BUG: read UNINITIALIZED byte from stack
and r0, r0, #254 @ clear only bit 0, preserve bits 1-7 (garbage)
add r0, r1 @ set bit 0
strb.w r0, [sp, #3] @ write back (bits 1-7 still garbage)
ldrb.w r0, [sp, #3] @ return value contains garbage in bits 1-7
add sp, #4
bx lr
在-O1 时、函数仅编译到 BX lr (优化器完全消除了问题)。