Gcc - c 内存分析

本文详细解析了Gcc-c编译器下C程序的内存布局,包括函数堆栈分配和不同内存区域如Stack、全局区(Bss区、Data区)、堆区的功能及使用方式。通过具体实例和汇编代码展示变量如何被分配到不同的内存区域。

Gcc - c 内存分析

Stack :函数地址,参数,局部非静态变量等

全局区:bss区、data区

Bss未初始化 :

Data初始化 :

堆区:动态库函数申请的,

   1:  .file    "memory.c"
   2:      .comm    dy_a,4,4 (Bss)
   3:  .globl dy_b
   4:      .data
   5:      .align 4
   6:      .type    dy_b, @object(Data)
   7:      .size    dy_b, 4
   8:  dy_b:
   9:      .long    90
  10:      .local    st_a
  11:      .comm    st_a,4,4
  12:      .align 4
  13:      .type    st_b, @object
  14:      .size    st_b, 4
  15:  st_b:
  16:      .long    8
  17:      .comm    p,4,4
  18:      .text
  19:  .globl function
  20:      .type    function, @function
  21:  function:
  22:      pushl    %ebp
  23:      movl    %esp, %ebp
  24:      subl    $40, %esp
  25:      movl    $190, -16(%ebp)
  26:      movl    $4, (%esp)
  27:      call    malloc
  28:      movl    %eax, p
  29:      movl    $4, (%esp)
  30:      call    malloc
  31:      movl    %eax, -12(%ebp)
  32:      leave
  33:      ret
  34:      .size    function, .-function
  35:      .data
  36:      .align 4
  37:      .type    func_st_b.1799, @object
  38:      .size    func_st_b.1799, 4
  39:  func_st_b.1799:
  40:      .long    900
  41:      .local    func_st_a.1798
  42:      .comm    func_st_a.1798,4,4
  43:      .ident    "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)"
  44:      .section    .note.GNU-stack,"",@progbits
  45:      #include<stdlib.h>
  46:  int dy_a ;
  47:  int dy_b = 90 ;
  48:  static int st_a ;
  49:  static int st_b= 8;
  50:  int * p ;
  51:  void function ( int ar)
  52:  {    
  53:      int func_dy_a ;
  54:      int func_dy_b = 190 ;
  55:      int * o ;
  56:      p = (int *)malloc(sizeof(int)) ;
  57:      o = (int *)malloc(sizeof(int)) ;
  58:      static int func_st_a ;
  59:      static int func_st_b = 900;
  60:  }

////////////////////////////////////

函数堆栈分配

C 程序:

   1:  Swap(int a )
   2:   
   3:  {
   4:   
   5:  a= 90 ;
   6:   
   7:  }
   8:   
   9:  Int main()
  10:   
  11:  {
  12:   
  13:  Int b = 888;
  14:   
  15:  Swap(b);
  16:   
  17:  }

对应的汇编代码

 

   1:  file "t3.c"
   2:   
   3:  .text
   4:   
   5:  .globl swap
   6:   
   7:  .type swap, @function
   8:   
   9:  swap:
  10:   
  11:  pushl %ebp
  12:   
  13:  movl %esp, %ebp
  14:   
  15:  movl $90, 8(%ebp)
  16:   
  17:  popl %ebp
  18:   
  19:  ret
  20:   
  21:  .size swap, .-swap
  22:   
  23:  .globl main
  24:   
  25:  .type main, @function
  26:   
  27:  main:
  28:   
  29:  pushl %ebp
  30:   
  31:  movl %esp, %ebp
  32:   
  33:  subl $20, %esp
  34:   
  35:  movl $888, -4(%ebp)
  36:   
  37:  movl -4(%ebp), %eax
  38:   
  39:  movl %eax, (%esp)
  40:   
  41:  call swap
  42:   
  43:  movl $0, %eax
  44:   
  45:  leave
  46:   
  47:  ret
  48:   
  49:  .size main, .-main
  50:   
  51:  .ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)"
  52:   
  53:  .section .note.GNU-stack,"",@progbits
  54:   

.下面就分析堆栈代码

wps_clip_image-2654

上面只考虑入栈,至于出栈大家可以自己推出

<think> 我们有一个关于GCC编译命令的问题。用户给出了四个命令,要求解释这些命令的含义。 1. `gcc -c main.c`:这个命令告诉GCC编译器将源文件`main.c`编译成目标文件(object file),但不进行链接。`-c`选项表示只编译不链接。输出文件默认是`main.o`(在Unix-like系统上)或`main.obj`(在Windows上)。 2. `gcc -c 2.c`:同样,这个命令将`2.c`编译成目标文件`2.o`。 3. `gcc -c 3.c`:将`3.c`编译成目标文件`3.o`。 4. `gcc -o myapp main.o 2.o 3.o`:这个命令将三个目标文件(`main.o`、`2.o`、`3.o`)链接成一个可执行文件。`-o myapp`表示输出的可执行文件名为`myapp`(在Windows上可能是`myapp.exe`)。 整个过程是将三个源文件分别编译成目标文件,然后将这些目标文件链接成最终的可执行程序。这样做的好处是,当其中一个源文件改变时,只需要重新编译那个文件,然后重新链接即可,而不需要重新编译所有文件。 解释一下编译和链接的过程: - 编译:将每个源文件(如.c文件)单独编译成目标文件(.o文件)。每个目标文件包含了该源文件的机器代码以及未解析的符号(例如,函数调用,但函数定义在其他文件中)。 - 链接:链接器将多个目标文件以及所需的库文件合并成一个可执行文件。它解决符号之间的引用(比如,一个目标文件中的函数调用在另一个目标文件中找到定义),并安排内存布局。 因此,上述命令序列是分步编译链接的典型做法。 现在,我们按照要求回答: </think> 这些命令是使用 GCC 编译器分步编译和链接 C 语言程序的典型流程,具体含义如下: ### 命令解释: 1. **`gcc -c main.c`** - `-c` 选项表示只编译不链接 - 将 `main.c` 源文件编译成目标文件 `main.o` - 生成:`main.o`(包含机器码但未链接的二进制文件) 2. **`gcc -c 2.c`** - 将 `2.c` 源文件单独编译成目标文件 `2.o` - 生成:`2.o` 3. **`gcc -c 3.c`** - 将 `3.c` 源文件单独编译成目标文件 `3.o` - 生成:`3.o` 4. **`gcc -o myapp main.o 2.o 3.o`** - `-o myapp` 指定输出可执行文件名 - 将三个目标文件 (`main.o`, `2.o`, `3.o`) 链接成最终可执行程序 - 生成:`myapp`(Linux)或 `myapp.exe`(Windows) ### 完整流程图: ```mermaid graph LR A[main.c] -->|gcc -c| B[main.o] C[2.c] -->|gcc -c| D[2.o] E[3.c] -->|gcc -c| F[3.o] B -->|gcc -o myapp| G[myapp] D -->|gcc -o myapp| G F -->|gcc -o myapp| G ``` ### 优势说明: 1. **增量编译**:修改单个文件时只需重新编译该文件(如改 `2.c` 只需重运行 `gcc -c 2.c`) 2. **编译加速**:避免每次修改都重新编译所有源文件 3. **模块化管理**:便于大型项目组织代码 ### 完整示例: 假设有三个文件: ```c // main.c #include <stdio.h> void func2(); // 声明在2.c中 void func3(); // 声明在3.c中 int main() { printf("Main started\n"); func2(); func3(); return 0; } ``` ```c // 2.c #include <stdio.h> void func2() { printf("Function 2\n"); } ``` ```c // 3.c #include <stdio.h> void func3() { printf("Function 3\n"); } ``` 执行命令后生成可执行文件: ```bash ./myapp ``` 输出: ``` Main started Function 2 Function 3 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值