本文测试C语言变量、常量在linux环境下不同情况的布局内存分布
体系结构:x86_64
操作系统:ubuntu 18.04
编译器: gcc 7.4.0
int var = 1;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 6
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 5
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 var
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x248:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 0001b8 000018 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 000050 000000 00 WA 0 0 1
[ 5] .comment PROGBITS 0000000000000000 000050 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 00007c 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000080 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001d0 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b8 0000f0 18 10 8 8
[10] .strtab STRTAB 0000000000000000 0001a8 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e8 000059 00 0 0 1
int var =1编译后,在可重定位目标文件.data节
static int var = 1;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 var
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 5
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x248:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 0001b8 000018 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 000050 000000 00 WA 0 0 1
[ 5] .comment PROGBITS 0000000000000000 000050 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 00007c 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000080 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001d0 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b8 0000f0 18 10 9 8
[10] .strtab STRTAB 0000000000000000 0001a8 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e8 000059 00 0 0 1
static int var =1编译后,在可重定位目标文件.data节
int var = 0;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 6
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 5
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 var
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x240:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 0001b0 000018 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00004c 000000 00 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 5] .comment PROGBITS 0000000000000000 00004c 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 000078 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000078 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001c8 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b0 0000f0 18 10 8 8
[10] .strtab STRTAB 0000000000000000 0001a0 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e0 000059 00 0 0 1
int var =0编译后,在可重定位目标文件.bss节
static int var = 0;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 4 var
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 5
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x240:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 0001b0 000018 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00004c 000000 00 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 5] .comment PROGBITS 0000000000000000 00004c 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 000078 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000078 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001c8 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b0 0000f0 18 10 9 8
[10] .strtab STRTAB 0000000000000000 0001a0 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e0 000059 00 0 0 1
static int var =0编译后,在可重定位目标文件.bss节
int var;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 6
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 5
8: 0000000000000004 4 OBJECT GLOBAL DEFAULT COM var
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
int var编译后,在可重定位目标文件.COMMON节
static int var;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 4 var
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 5
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x240:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000c 00 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 0001b0 000018 18 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00004c 000000 00 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 5] .comment PROGBITS 0000000000000000 00004c 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 000078 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000078 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001c8 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b0 0000f0 18 10 9 8
[10] .strtab STRTAB 0000000000000000 0001a0 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e0 000059 00 0 0 1
static int var 编译后,在可重定位目标文件.bss节
const int var = 0;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 5
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 var
10: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x248:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000b 00 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00004b 000000 00 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00004b 000000 00 WA 0 0 1
[ 4] .rodata PROGBITS 0000000000000000 00004c 000004 00 A 0 0 4
[ 5] .comment PROGBITS 0000000000000000 000050 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 00007c 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000080 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001d0 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b8 000108 18 10 9 8
[10] .strtab STRTAB 0000000000000000 0001c0 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e8 00005c 00 0 0 1
const int var = 0编译后,在可重定位目标文件.rodata节
static const int var = 0;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 0 SECTION LOCAL DEFAULT 4
6: 0000000000000000 4 OBJECT LOCAL DEFAULT 4 var
7: 0000000000000000 0 SECTION LOCAL DEFAULT 6
8: 0000000000000000 0 SECTION LOCAL DEFAULT 7
9: 0000000000000000 0 SECTION LOCAL DEFAULT 5
10: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 12 section headers, starting at offset 0x248:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000b 00 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00004b 000000 00 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00004b 000000 00 WA 0 0 1
[ 4] .rodata PROGBITS 0000000000000000 00004c 000004 00 A 0 0 4
[ 5] .comment PROGBITS 0000000000000000 000050 00002c 01 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 00007c 000000 00 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 000080 000038 00 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 0001d0 000018 18 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 0000b8 000108 18 10 10 8
[10] .strtab STRTAB 0000000000000000 0001c0 000010 00 0 0 1
[11] .shstrtab STRTAB 0000000000000000 0001e8 00005c 00 0 0 1
static const int var = 0编译后,在可重定位目标文件.rodata节
const int var;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 6
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 5
8: 0000000000000004 4 OBJECT GLOBAL DEFAULT COM var
9: 0000000000000000 12 FUNC GLOBAL DEFAULT 1 say
const int var 编译后,在可重定位目标文件.COMMON节
本地常量var未初始化:
static const int var;
int say() {
return var;
}
root@nemo-VirtualBox:~/workspace/learn# gcc -c test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.oSymbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 2
4: 0000000000000000 0 SECTION LOCAL DEFAULT 3
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 var
6: 0000000000000000 0 SECTION LOCAL DEFAULT 5
7: 0000000000000000 0 SECTION LOCAL DEFAULT 6
8: 0000000000000000 0 SECTION LOCAL DEFAULT 4
9: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 say
root@nemo-VirtualBox:~/workspace/learn# readelf -S -W test.o
There are 11 section headers, starting at offset 0x220:Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00000b 00 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00004b 000000 00 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00004c 000004 00 WA 0 0 4
[ 4] .comment PROGBITS 0000000000000000 00004c 00002c 01 MS 0 0 1
[ 5] .note.GNU-stack PROGBITS 0000000000000000 000078 000000 00 0 0 1
[ 6] .eh_frame PROGBITS 0000000000000000 000078 000038 00 A 0 0 8
[ 7] .rela.eh_frame RELA 0000000000000000 0001b0 000018 18 I 8 6 8
[ 8] .symtab SYMTAB 0000000000000000 0000b0 0000f0 18 9 9 8
[ 9] .strtab STRTAB 0000000000000000 0001a0 000010 00 0 0 1
[10] .shstrtab STRTAB 0000000000000000 0001c8 000054 00 0 0 1
static const int var 编译后,在可重定位目标文件.bss节
index | 定义 | 属性 | 范围 | 赋值 | 所在位置 |
1 | int a = 1 | 变量 | 全局 | any(除默认空值) | .data |
2 | static int a = 1 | 变量 | 本地 | any(除默认空值) | .data |
3 | int a = 0 | 变量 | 全局 | 默认空值 | .bss |
4 | static int a = 0 | 变量 | 本地 | 默认空值 | .bss |
5 | int a | 变量 | 全局 | 未初始化 | .COMMON |
6 | static int a | 变量 | 本地 | 未初始化 | .bss |
7 | const int a = 0 | 常量 | 全局 | any | .rodata |
8 | static const int a = 0 | 常量 | 本地 | any | .rodata |
9 | const int a | 常量 | 全局 | 未初始化 | .COMMON |
10 | static const int a | 常量 | 本地 | 未初始化 | .bss |
由于未初始化的本地常量被放置在.bss节中,而.bss节中数据是可以修改的,所以可以通过指针修改这个值,再通过指针获取修改的值!
示例:
#include
static const int var;
void set_var(int);
int get_var();
int main() {
set_var(10);
printf("%d\n", get_var());
}
void set_var(int v) {
int *p = &var;
*p = v;
}
int get_var() {
int *p = &var;
return *p;
}
root@nemo-VirtualBox:~/workspace/learn# gcc test.c
test.c: In function ‘set_var’:
test.c:19:14: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p = &var;
^
test.c: In function ‘get_var’:
test.c:24:14: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p = &var;
^
root@nemo-VirtualBox:~/workspace/learn# ./a.out
10
因为var在.bss上,所以我们成功修改了本地常量的值。
我们做个小小的修改,为本地常量赋初始值为0(好像和上面没有任何区别),但是。。。
#include
static const int var = 0;
void set_var(int);
int get_var();
int main() {
set_var(10);
printf("%d\n", get_var());
}
void set_var(int v) {
int *p = &var;
*p = v;
}
int get_var() {
int *p = &var;
return *p;
}
root@nemo-VirtualBox:~/workspace/learn# gcc test.c
test.c: In function ‘set_var’:
test.c:19:14: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p = &var;
^
test.c: In function ‘get_var’:
test.c:24:14: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
int *p = &var;
^
root@nemo-VirtualBox:~/workspace/learn# ./a.out
Segmentation fault (core dumped)
因为我们为本地常量赋了初值0,所以他被编译器放置在.rodata节中,而.rodata节中数据是只读,当写入时操作系统发生段错误。为了避免一些奇怪的错误,我们建议常量一定要赋值(即使值是0)