問題は、配列がスタック上にあり、コンパイラが古すぎて、過剰に整列されたスタック変数をサポートできないことだと思います。GCC 4.6以降では、そのバグが修正されました。
C11 / C ++ 112alignas(64) float a[4];
アラインメントの任意の累乗で機能します。使用して
いたGNUCも__attribute__((aligned(x)))
同様です。
(C11では#include <stdalign.h>
、#define alignas _Alignas
:cpprefの場合)。
しかし、4kページ境界への非常に大きな配置の場合、スタックに配置したくない場合があります。
関数の開始時にスタックポインタは何でもかまいません。必要以上に割り当てて調整しない限り、配列を整列させる方法はありません。(コンパイラはand rsp, -4096
、割り当てられた0〜4088バイトのいずれかを使用するか、同等であり、そのスペースが十分に大きいかどうかで分岐することは可能ですが、配列または他のローカルのサイズよりもはるかに大きい巨大なアラインメントのために実行されません。通常の場合ではありません。)
配列を関数からグローバル変数に移動すると、機能するはずです。あなたができる他のことはそれをローカル変数として保持することです(これは非常に良いことです)が、それを作りますstatic
。これにより、スタックに保存されなくなります。配列のコピーは1つしかないため、これらの方法はどちらもスレッドセーフでも再帰セーフでもないことに注意してください。
このコードで:
#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
これが期待されていることです。元のコードでは、あなたと同じようにランダムな値を取得します。