Я считаю, что проблема в том, что ваш массив находится в стеке, а ваш компилятор слишком стар, чтобы поддерживать переменные стека с чрезмерным выравниванием. GCC 4.6 и более поздние версии исправили эту ошибку.
C11/C++11 alignas(64) float a[4];
Просто работает для любой степени двойки выравнивания.
То же самое делает и GNU C __attribute__((aligned(x)))
в том виде, в каком вы его использовали.
(В C11 #include <stdalign.h>
вместо #define alignas _Alignas
: cppref).
Но в вашем случае очень большого выравнивания до границы страницы 4k вы можете не захотеть, чтобы оно было в стеке.
Поскольку указатель стека может быть любым, когда функция запускается, нет способа выровнять массив, не выделяя намного больше, чем вам нужно, и не настраивая его. (Компиляторы будут and rsp, -4096
или эквивалентными и не будут использовать ни один из выделенных байтов от 0 до 4088; ветвление в зависимости от того, достаточно ли это пространство или нет, было бы возможно, но не делается, потому что огромные выравнивания намного больше, чем размер массива или другие Местные жители не являются нормальным случаем.)
Если вы переместите массив из функции в глобальную переменную, он должен работать. Другая вещь, которую вы могли бы сделать, это сохранить ее как локальную переменную (что очень хорошо), но сделать ее 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
что и ожидается. С вашим исходным кодом я просто получаю случайные значения, как и вы.
person
Zifre
schedule
08.05.2009