堆栈变量是否由 GCC __attribute__((aligned(x))) 对齐? [英] Are stack variables aligned by the GCC __attribute__((aligned(x)))?

查看:30
本文介绍了堆栈变量是否由 GCC __attribute__((aligned(x))) 对齐?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

#include <stdio.h>

int
main(void)
{
        float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0};
        printf("%p %p %p %p
", &a[0], &a[1], &a[2], &a[3]);
}

我有以下输出:

0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac

为什么a[0]的地址不是0x1000的倍数?

Why the address of a[0] is not a multiple of 0x1000?

__attribute__((aligned(x))) 到底是做什么的?我误解了这个的解释?

What exactly __attribute__((aligned(x))) does? I misunderstood this explanation?

我使用的是 gcc 4.1.2.

I'm using gcc 4.1.2.

推荐答案

我认为问题在于您的数组在堆栈上,而您的编译器太旧,无法支持过度对齐的堆栈变量.GCC 4.6 及更高版本修复了该错误.

I believe the problem is that your array is on the stack, and that your compiler is too old to support over-aligned stack variables. GCC 4.6 and later fixed that bug.

C11/C++11 alignas(64) float a[4]; 仅适用于任何 2 次方对齐.
GNU C __attribute__((aligned(x))) 也是如此.

C11/C++11 alignas(64) float a[4]; Just Works for any power of 2 alignment.
So does the GNU C __attribute__((aligned(x))) as you were using it.

(在 C11 中,#include 用于 #define alignas _Alignas:cppref).

(In C11, #include <stdalign.h> for the #define alignas _Alignas: cppref).

但是在对齐非常大的情况下,对于 4k 页面边界,您可能不希望它在堆栈中.

But in your case of a very large alignment, to a 4k page boundary, you may not want it on the stack.

因为在函数启动时堆栈指针可以是任何东西,所以没有办法对齐数组而不分配比你需要的多得多的东西并调整它.(编译器将 和 rsp, -4096 或等效的,并且不使用分配的 0 到 4088 字节中的任何一个;分支该空间是否足够大是可能的,但没有完成,因为巨大比数组大小或其他局部变量大得多的对齐不是正常情况.)

Because the stack pointer could be anything when the function starts, there is no way to align the array without allocating a lot more than you need and adjusting it. (Compilers will and rsp, -4096 or equivalent and not use any of the 0 to 4088 bytes that allocated; branching on whether that space is large enough or not would be possible but isn't done because huge alignments much larger than the size of the array or other locals are not the normal case.)

如果您将数组移出函数并移入全局变量,它应该可以工作.您可以做的另一件事是将其保留为局部变量(这是一件非常好的事情),但使其成为static.这将防止它被存储在堆栈中.请注意,这两种方式都不是线程安全的或递归安全的,因为只有一个数组副本.

If you move the array out of the function and into a global variable, it should work. The other thing you could do is keep it as a local variable (which is a very good thing), but make it static. This will prevent it from being stored on the stack. Beware that both of these ways are not thread-safe or recursion-safe, since there will be only one copy of the array.

使用此代码:

#include <stdio.h>

float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0};

int
main(void)
{
        printf("%p %p %p %p
", &a[0], &a[1], &a[2], &a[3]);
}

我明白了:

0x804c000 0x804c004 0x804c008 0x804c00c

这是预期的.使用您的原始代码,我只是像您一样获得随机值.

which is what is expected. With your original code, I just get random values like you did.

这篇关于堆栈变量是否由 GCC __attribute__((aligned(x))) 对齐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆