스택 변수가 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
'developer tip' 카테고리의 다른 글
Swift에서 뷰 컨트롤러와 다른 객체간에 데이터를 어떻게 공유합니까? (0) | 2020.09.14 |
---|---|
.json ()이 프라 미스를 반환하는 이유는 무엇입니까? (0) | 2020.09.14 |
Java에서 시간 초과가있는 일부 차단 메서드를 어떻게 호출합니까? (0) | 2020.09.14 |
C ++에 __CLASS__ 매크로가 있습니까? (0) | 2020.09.14 |
MySQL을 다시 시작하지 않고 MySQL의 느린 쿼리 로그를 활성화하려면 어떻게해야합니까? (0) | 2020.09.14 |