为什么我的静态变量在 运行 上不对齐?
Why does my static variable get dis-aligned on running?
我正在编写代码测试来处理二次幂边界上的内存,我需要在 1MB 边界上有一个 1MB 的内存块用于测试。该代码适用于小块,但不适用于大块。最终,我发现这是因为我应该对齐的数据没有对齐到 1MB 的边界。
(显然我可以解决这个问题,但我想知道发生了什么。)
此代码编译时没有警告,objdump 说变量位于合理的地址,但是当我 运行 它时,它在 4K 边界上对齐,而不是 1M。
cat x.c ; gcc --version ; uname -a ; gcc -Wall x.c && ( objdump -x a.out | grep test_data ; ./a.out )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct data {
char memory[1024*1024];
};
static struct data __attribute__(( aligned( 0x100000 ) )) test_data = { 0 };
int main( int argc, const char **argv )
{
printf( "test_data is actually here: %p\n", &test_data );
return 0;
}
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Linux Lubuntutu 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
0000000000400000 l O .bss 0000000000100000 test_data
test_data is actually here: 0x5600cb9fe000
运行 gdb下很有意思:
Reading symbols from ./a.out...done.
(gdb) display &test_data
1: &test_data = (struct data *) 0x400000 <test_data>
(gdb) start
Temporary breakpoint 1 at 0x659: file x.c, line 13.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe038) at x.c:13
13 printf( "test_data is actually here: %p\n", &test_data );
1: &test_data = (struct data *) 0x555555954000 <test_data>
(gdb) print &test_data.memory[16]
= 0x555555954010 <test_data+16> ""
(gdb) c
Continuing.
test_data is actually here: 0x555555954000
这是加载程序或可能是安全模块的功能。
代码已在内存中移动了类似的数量,大概是地址-space布局随机化的一部分,但它是随机数量的 4k 页,这将破坏由请求的任何粗对齐程序。
静态链接程序可以阻止这种情况发生,至少目前是这样。
我正在编写代码测试来处理二次幂边界上的内存,我需要在 1MB 边界上有一个 1MB 的内存块用于测试。该代码适用于小块,但不适用于大块。最终,我发现这是因为我应该对齐的数据没有对齐到 1MB 的边界。
(显然我可以解决这个问题,但我想知道发生了什么。)
此代码编译时没有警告,objdump 说变量位于合理的地址,但是当我 运行 它时,它在 4K 边界上对齐,而不是 1M。
cat x.c ; gcc --version ; uname -a ; gcc -Wall x.c && ( objdump -x a.out | grep test_data ; ./a.out )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct data {
char memory[1024*1024];
};
static struct data __attribute__(( aligned( 0x100000 ) )) test_data = { 0 };
int main( int argc, const char **argv )
{
printf( "test_data is actually here: %p\n", &test_data );
return 0;
}
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Linux Lubuntutu 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
0000000000400000 l O .bss 0000000000100000 test_data
test_data is actually here: 0x5600cb9fe000
运行 gdb下很有意思:
Reading symbols from ./a.out...done.
(gdb) display &test_data
1: &test_data = (struct data *) 0x400000 <test_data>
(gdb) start
Temporary breakpoint 1 at 0x659: file x.c, line 13.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe038) at x.c:13
13 printf( "test_data is actually here: %p\n", &test_data );
1: &test_data = (struct data *) 0x555555954000 <test_data>
(gdb) print &test_data.memory[16]
= 0x555555954010 <test_data+16> ""
(gdb) c
Continuing.
test_data is actually here: 0x555555954000
这是加载程序或可能是安全模块的功能。
代码已在内存中移动了类似的数量,大概是地址-space布局随机化的一部分,但它是随机数量的 4k 页,这将破坏由请求的任何粗对齐程序。
静态链接程序可以阻止这种情况发生,至少目前是这样。