进程的内存段篇:C/C++堆区、栈区、常量区、静态数据区、代码区详解

时间:2024-05-22 19:14:51

参考:
【1】https://blog.****.net/u012942555/article/details/48876447
【2】《C程序设计语言 第二版新版》第4章

五个段

https://www.cnblogs.com/TS-qrt/articles/cmemery.html
进程的内存段篇:C/C++堆区、栈区、常量区、静态数据区、代码区详解
BSS( Block Started by Symbol 全局未初始化段)、数据段(data Segment)。
在C语言中,BSS段和数据段都用于保存全局变量和静态变量,不同的是BSS段中的全局变量和静态变量都是未初始化的。
这里有个问题就是,不同博客对于数据段是否包括BSS段的描述不同,个人认为C是两者分开,C++中是包含的。
进程的内存段篇:C/C++堆区、栈区、常量区、静态数据区、代码区详解
来自:https://blog.****.net/weixin_41143631/article/details/81221512

*储存区

https://www.cnblogs.com/QG-whz/p/5060894.html
是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,稍后调用free可把内存交还。
*存储是C++中通过new和delete动态分配和释放对象的抽象概念,通过new来申请的内存区域可称为*存储区。
基本上,所有的C++编译器
默认使用来实现*存储*,也即是缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时藉由new运算符分配的对象,说它在堆上也对,说它在*存储区上也正确。也可以通过重载操作符,改用其他内存来实现*存储,例如全局变量做的对象池,这时*存储区就区别于堆了。

4个与储存类型相关的关键字

1.auto

auto只能用来标识局部变量的存储类型。auto是默认的存储类型,不需要显示的指定。auto标识的变量存储在区中。

2.extern

extern用来声明在当前文件中引用,但是是在当前项目的其它文件中定义全局变量***。
如果全局变量
未被初始化
*,那么将被存在BBS区(静态数据区)中,且在编译时自动将其值赋值为0;
如果已经被初始化,就被存在数据区中。
全局变量,不管是否被初始化,其生命周期是整个程序运行过程。为了节省内存空间,在当前文件中使用extern来声明其它文件中定义的全局变量时,就不会再为其分配内存空间

3.register

声明为register的变量在由内存调入到CPU寄存器后,则常驻在CPU的寄存器中,因此访问register变量将在很大程度上提高效率,因为省去了变量由内存调入到寄存器过程中的好几个指令周期。但编译器可以忽略此选项。

4. static

被声明为静态类型的变量,无论是全局的还是局部的,都存储在数据区中,其生命周期为整个程序。静态变量如果没有被初始化,则自动初始化为0只能够初始化一次
函数声明为static,除了对该函数声明所在的文件可见外,其他文件都无法访问。

进程的内存段篇:C/C++堆区、栈区、常量区、静态数据区、代码区详解
常量区: 存放常量的区间,如字符串常量等,注意在常量区存放的数据一旦初始化后就不能被修改。 程序结束后由系统释放。

char s1[] = “abcdef”;
//1) s1在静态区,"abcdef"无需额外存放,就是数组s1内部,总共占用一个串的内存
const char *p =“abcdef”;
//2)p在静态区,“abcdef”,必须额外存放(在常量区,通常也在静态区),/总共占用一个指针,和一个串的内存

free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容是未定义的。

非静态的全局变量可以用extern扩展到组成源程序的多个文件中,而静态的全局变量的作用域只限于本文件,不能扩展到其它文件。把全局变量改变为静态全局变量后是改变了它的作用域,限制了它的使用范围。

static函数的作用域仅在本文件,在内存中只有一份,普通函数在每个被调用中维持一份拷贝。