C语言变量内存布局

本文测试C语言变量、常量在linux环境下不同情况的布局内存分布

体系结构:x86_64

操作系统:ubuntu 18.04

编译器:    gcc 7.4.0

变量

已初始化

全局变量var初始化为1:

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.o

Symbol 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节


本地变量var初始化为1:

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.o

Symbol 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节


全局变量var初始化为0:

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.o

Symbol 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节


本地变量初始化为0:

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.o

Symbol 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节

未初始化

全局变量var未初始化:

int var;

int say() {
    return var;
}

root@nemo-VirtualBox:~/workspace/learn# gcc -c  test.c
root@nemo-VirtualBox:~/workspace/learn# readelf -s -W test.o

Symbol 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.o

Symbol 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节


常量

已初始化

全局常量var已初始化:

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.o

Symbol 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节


本地常量var已初始化:

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.o

Symbol 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节


未初始化

全局常量var未初始化:

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.o

Symbol 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.o

Symbol 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
  • 变量初始化为非默认空值时,编译器将其放置在.data节中(1,2)
  • 变量初始化为默认空值时,由于.bss不占空间,编译器优化,将其放置在.bss节中(3,4)
  • 未初始化的全局变量,由于是弱符号,编译期无法确定引用地址,所以放置在.COMMON节中,由连接器决定引用地址(5)
  • 未初始化的本地变量,由于作用域在本模块,所以编译器可以确定引用此变量的地址,同时因为未初始化,所以放置在.bss节中(6)
  • 常量初始化后,编译器将其放置在.rodata中(7,8)
  • 未初始化的全局常量,由于是弱符号,编译期无法确定引用地址,所以放置在.COMMON节中,由连接器决定引用地址(9)
  • 未初始化的本地常量,由于作用域在本模块,所以编译器可以确定引用此常量的地址,同时因为未初始化,所以放置在.bss节中(10)

问题:

由于未初始化的本地常量被放置在.bss节中,而.bss节中数据是可以修改的,所以可以通过指针修改这个值,再通过指针获取修改的值!

示例:

#include <stdio.h>

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 <stdio.h>

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)

猜你喜欢

转载自blog.csdn.net/u013259665/article/details/100019121