developer tip

스택 변수가 GCC __attribute __ ((aligned (x)))에 의해 정렬됩니까?

optionbox 2020. 9. 14. 08:19
반응형

스택 변수가 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\n", &a[0], &a[1], &a[2], &a[3]);
}

그리고 다음과 같은 출력이 있습니다.

0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac

의 주소 a[0]가의 배수가 아닌 이유는 무엇 0x1000입니까?

정확히 무엇입니까 __attribute__((aligned(x)))? 설명을 오해 했습니까?

gcc 4.1.2를 사용하고 있습니다.


문제는 어레이가 스택에 있다는 것입니다. 스택 포인터는 함수가 시작될 때 무엇이든 될 수 있기 때문에 필요한 것보다 더 많이 할당하고 조정하지 않고는 배열을 정렬 할 수있는 방법이 없습니다. 배열을 함수에서 전역 변수로 이동하면 작동합니다. 당신이 할 수있는 다른 일은 그것을 지역 변수로 유지하는 것입니다 (매우 좋은 것입니다) static. 이렇게하면 스택에 저장되지 않습니다. 배열의 복사본이 하나만 있기 때문에이 두 가지 방법 모두 스레드로부터 안전하거나 재귀로부터 안전하지 않습니다.

이 코드로 :

#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\n", &a[0], &a[1], &a[2], &a[3]);
}

나는 이것을 얻는다 :

0x804c000 0x804c004 0x804c008 0x804c00c

예상되는 것입니다. 원래 코드로 나는 당신이했던 것처럼 임의의 값을 얻습니다.


정렬 된 속성 이 스택 변수와 함께 작동하지 않게 하는 gcc의 버그가 있습니다 . 아래 링크 된 패치로 수정 된 것 같습니다. 아래 링크에는 문제에 대한 많은 논의도 포함되어 있습니다.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660

위의 코드를 RedHat 5.7 상자의 두 가지 다른 버전의 gcc : 4.1.2로 시도했지만 문제와 비슷하게 실패했습니다 (로컬 배열이 0x1000 바이트 경계에 정렬되지 않음). 그런 다음 RedHat 6.3에서 gcc 4.4.6으로 코드를 시도했는데 완벽하게 작동했습니다 (로컬 배열이 정렬 됨). Myth TV 사람들도 비슷한 문제가있었습니다 (위의 gcc 패치가 수정 한 것 같습니다).

http://code.mythtv.org/trac/ticket/6535

어쨌든 gcc에서 버그를 발견 한 것 같습니다. 이는 이후 버전에서 수정 된 것으로 보입니다.


Recent GCC (tested with 4.5.2-8ubuntu4) appear to work as expected with the array aligned properly.

#include <stdio.h>

int main(void)
{
    float a[4] = { 1.0, 2.0, 3.0, 4.0 };
    float b[4] __attribute__((aligned(0x1000))) = { 1.0, 2.0, 3.0, 4.0 };
    float c[4] __attribute__((aligned(0x10000))) = { 1.0, 2.0, 3.0, 4.0 };

    printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]);
    printf("%p %p %p %p\n", &b[0], &b[1], &b[2], &b[3]);
    printf("%p %p %p %p\n", &c[0], &c[1], &c[2], &c[3]);
}

I get:

0x7ffffffefff0 0x7ffffffefff4 0x7ffffffefff8 0x7ffffffefffc
0x7ffffffef000 0x7ffffffef004 0x7ffffffef008 0x7ffffffef00c
0x7ffffffe0000 0x7ffffffe0004 0x7ffffffe0008 0x7ffffffe000c

Alignement is not effective for all types. You should consider using a structure to see the attributes in action:

#include <stdio.h>

struct my_float {
        float number;
}  __attribute__((aligned(0x1000)));

struct my_float a[4] = { {1.0}, {2.0}, {3.0}, {4.0} };

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

And then, you'll read:

0x603000 0x604000 0x605000 0x606000

Which is what you were expecting.

Edit: Pushed by @yzap and following @Caleb Case comment, the initial problem is due to GCC version only. I've checked on GCC 3.4.6 vs GCC 4.4.1 with the requester's source code:

$ ./test_orig-3.4.6
0x7fffe217d200 0x7fffe217d204 0x7fffe217d208 0x7fffe217d20c
$ ./test_orig-4.4.1
0x7fff81db9000 0x7fff81db9004 0x7fff81db9008 0x7fff81db900c

It's now obvious that older GCC versions (somewhere before 4.4.1) shows alignment pathologies.

Note 1: My proposed code doesn't answer the question which I understood as "aligning each field of the array".

Note 2: Bringing non-static a[] inside main() and compiling with GCC 3.4.6 breaks the alignment directive of the array of struct but keeps 0x1000 distance between structs... still bad ! (see @zifre answer for workarounds)

참고URL : https://stackoverflow.com/questions/841433/are-stack-variables-aligned-by-the-gcc-attribute-alignedx

반응형