【问题标题】:GCC variables alignment issuesGCC 变量对齐问题
【发布时间】:2017-04-13 05:37:32
【问题描述】:

我正在为 Microblaze 处理器使用 GCC 编译器。 最近我遇到了一个变量对齐的问题。我注意到有时编译器会将静态变量分配给未对齐的地址(该地址不能被 4 整除),因此如果我将未对齐变量的指针发送给任何函数,我都会得到未对齐的访问硬件异常。

我有两个关于该主题的问题:

  • 如何确保所有静态变量都对齐?有没有强制要求的标志?目前我正在使用变量属性:

    __attribute__((aligned(4)))
    

    但这很不舒服,因为我需要为我拥有的每个静态变量定义它,这没有意义。

  • 有没有办法确保我的函数局部变量(分配在堆栈中)对齐?我的意思是有没有办法确保我的堆栈头对齐,每个函数都使用堆栈的对齐部分,并且在堆栈中分配的任何变量都是对齐的。

谢谢。

【问题讨论】:

  • 这听起来像是一个编译器错误。编译器应根据目标架构处理对齐。
  • 注意:不要使用存在标准替代方案的编译器扩展。使用 _Alignas 说明符(分别是 stdalign.h 名称)。您可以使用_Alignof 检查编译器应该期望的对齐方式。在提交错误报告之前,我会非常彻底地测试这个问题。
  • 我已经测试了对齐方式。对于大小为 1 的类型,对齐方式为 1,因此可能会获得未对齐的变量。但我的问题是,是否有一个标志使默认对齐至少为 4,或者类似的东西。
  • 你传递给 gcc 的标志是什么?

标签: c gcc memory-alignment compiler-flags microblaze


【解决方案1】:

AFAIK 无法告诉 GCC 您要对整个编译单元强制执行某种对齐。那就是没有编译器标志类似于“alignment_unit 4”。

我不是该主题的专家(尤其不是 Microblaze 软核),但我对针对我 PC 的 Intel x64 CPU 的 GCC 和针对 ARM Cortex-M4 微控制器的 IAR C 做了一些实验。

设置 1:全局(文件级)变量

static uint64_t a = 0;
static uint8_t b = 0;
static uint16_t c = 0;
static uint16_t d = 0;
static uint8_t e = 0;

int main()
{   
    printf("&a = %u\n", &a);
    printf("&b = %u\n", &b);
    printf("&c = %u\n", &c);
    printf("&d = %u\n", &d);
    printf("&e = %u\n", &e);

    return 0;
}

设置 2:本地(函数级)变量

void some_func()
{    
    uint64_t a = 0;
    uint8_t b = 0;
    uint16_t c = 0;
    uint16_t d = 0;
    uint8_t e = 0;

    printf("&a = %u\n", &a);
    printf("&b = %u\n", &b);
    printf("&c = %u\n", &c);
    printf("&d = %u\n", &d);
    printf("&e = %u\n", &e);
}

int main()
{   
    some_func();    
    return 0;
}

我关闭了所有优化。

这两种设置都没有导致 4 字节(或 PC 为 8 字节)对齐的变量地址。编译器/平台组合都是这种情况。

我能想到的唯一可能的解决方案(尽管它可能不优雅)是为自定义类型创建一个标头并将以下 typedef 放入其中:

typedef __attribute__((aligned(4))) uint64_t ui64_aligned;
typedef __attribute__((aligned(4))) uint32_t ui32_aligned;
typedef __attribute__((aligned(4))) uint16_t ui16_aligned;
typedef __attribute__((aligned(4))) uint8_t ui8_aligned;

然后在需要时使用“对齐类型”。这样,您将同时拥有“自定义对齐”和“自动对齐”类型,并且您也不会损害代码的可读性(太多......)。

我知道这不是您正在寻找的解决方案,但这至少有效(就我的测试而言)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-11
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2010-10-24
    • 2013-01-07
    相关资源
    最近更新 更多