This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] RM57L843:RM57L843:ARM-CGT-CLANG:匿名位字段填充不是在具有运行时值的指定初始化值中初始化的零

Guru**** 2815985 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/1624770/rm57l843-rm57l843-arm-cgt-clang-anonymous-bit-field-padding-not-zero-initialized-in-designated-initializer-with-runtime-value

部件号: 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 (优化器完全消除了问题)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    ——在我们的编译器团队中循环。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我怀疑这是未定义的行为。  如果我是对的、这意味着编译器可能会生成任何结果、包括您期望的结果。  结果会随着编译选项的变化、编译器版本的变化等而变化  在我和我的团队一起回顾之后、我会回到您的身边。

    谢谢。此致、

    -乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您的 C 代码不能假设 位字段结构的匿名填充位的内容。  我对这些细节是正确的...

    编译器可以生成任何结果、包括您期望的结果。  结果可能会随着构建选项的变化、编译器版本的变化等而变化。

    为了强调这一点、请考虑 在编译器资源管理器上进行这个实验。  它使用不同版本的 Arm Clang 编译器。  版本 19.x 会生成您在上面显示的代码。  版本 20.x 会生成非常不同的代码。

    谢谢。此致、

    -乔治