堆&栈&进程内存空间分配方式&static

目录

  • 堆(链表维护,内存不连续)
  • 进程的内存空间分配方式
    • 用nm命令查看全局变量在bss段,data段
  • static用法和作用

  1. 大小
    Linux: 10M = 10240KB

    windows: 1M = 1024KB

  2. 可以静态分配(在编译阶段就能确定大小,由编译器进行分配);

    也可以动态分配(使用alloca()函数可以动态分配栈的内存空间,释放的时候由编译器自己释放,不需要手动释放)

堆(链表维护,内存不连续)

  1. 不能静态分配,只能动态分配(堆的申请是在执行过程中执行的)

    堆是使用malloc()、calloc()、realloc()等函数动态分配的

  2. 在堆上频繁的调用new/delete容易产生内存碎片

进程的内存空间分配方式

进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。

  1. 代码区(只读)(低地址)

    • 程序代码
    • 数字常量
  2. 静态数据区(中地址)

    • 字符串常量(只读数据段,挨着数据段)

    • 全局变量(已经初始化)

    • 静态变量(static修饰)

      c语言中static的语义
      1.static变量:
      1).局部
      只初始化一次,静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。
      ​ 2).全局
      2.static函数(也叫内部函数)只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。

  3. 动态数据区(高地址)

    • :链式结构(向高地址方向增长)
    • :线性结构(函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。)(向低地址方向增长)
    • 本地变量
    • 程序通过堆栈的基地址和偏移量来访问本地变量。
      堆&栈&进程内存空间分配方式&static_第1张图片
      下图来源:Unix环境高级编程一书中7.6小节
      堆&栈&进程内存空间分配方式&static_第2张图片

用nm命令查看全局变量在bss段,data段

//test.c
#include 

int global_variable;
int initialized_global_variables = 1;

int add(int a, int b){
	return a + b;
}

int main(){

	int a = 1;
	printf("hello %d\n", add(a, 1));
	
	return 0;
}

局部变量a在栈中,栈和堆在程序运行时才有,所以可执行文件看不到a

[root@izbp1bvlfc3omk6i0e7ht2z C]# nm test.out
/*********************************
000000000040052d T add//静态绑定函数地址
*********************************/
0000000000601038 B __bss_start
0000000000601038 b completed.6355
0000000000601030 D __data_start
0000000000601030 W data_start
0000000000400470 t deregister_tm_clones
00000000004004e0 t __do_global_dtors_aux
0000000000600e18 t __do_global_dtors_aux_fini_array_entry
0000000000400608 R __dso_handle
0000000000600e28 d _DYNAMIC
0000000000601038 D _edata
0000000000601040 B _end
00000000004005f4 T _fini
0000000000400500 t frame_dummy
0000000000600e10 t __frame_dummy_init_array_entry
0000000000400768 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
/********************************************
000000000060103c B global_variable//未初始化在bss段
********************************************/
                 w __gmon_start__
000000000040061c r __GNU_EH_FRAME_HDR
00000000004003e0 T _init
0000000000600e18 t __init_array_end
0000000000600e10 t __init_array_start
/********************************************
0000000000601034 D initialized_global_variables//初始化在data段
********************************************/
0000000000400600 R _IO_stdin_used
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
00000000004005f0 T __libc_csu_fini
0000000000400580 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400541 T main
/********************************************
                 U printf@@GLIBC_2.2.5//printf需要运行时动态链接,此时不绑定函数地址
********************************************/               
00000000004004a0 t register_tm_clones
0000000000400440 T _start
0000000000601038 D __TMC_END__

堆&栈&进程内存空间分配方式&static_第3张图片

static用法和作用

  1. 声明静态变量

    • 全局变量:静态全局变量仅对当前文件可见,其他文件不可访问,避免不同文件变量同名的冲突,降低耦合性。

    • 局部变量:存储于进程的全局数据区,编译器自动对其初始化,函数结束,内存空间也不会回收,作用域在函数体内,有利于程序模块化。

  2. 声明函数

    • 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
    • 不同的文件可以使用相同名字的静态函数,互不影响

你可能感兴趣的:(计算机基础,#,C语言,linux)