内存分区与C/C++开发

感谢前辈 Dablelv 的分享
原文 - https://blog.csdn.net/k346k346/article/details/45592329

正确的理解C/C++程序的内存分区,有助于高效准确的写代码和清晰明确的逆向破解。
网络上流形两大版本内存分区,分别为:

  1. 五大内存分区:堆、栈、全局/静态存储区、自由存储区和常量存储区。
  2. 五大内存分区:堆、栈、全局/静态存储区、字符串常量区和代码区。

本文按四大内存分区讲解:堆、栈、静态存储区和代码区。

堆区:

由程序猿手动申请,手动释放,若不手动释放,程序结束后由系统回收,生命周期是整个程序运行期间。使用malloc或者new进行堆的申请,堆的总大小为机器的虚拟内存的大小。

  • new操作符本质上是使用了malloc进行内存的申请,new和malloc的区别如下:
  1. malloc是C语言中的函数,而new是C++中的操作符。
  2. malloc申请之后返回的类型是void*,而new返回的指针带有类型。
  3. malloc只负责内存的分配而不会调用类的构造函数,而new不仅会分配内存,而且会自动调用类的构造函数。

栈区:

由系统进行内存的管理。主要存放函数的参数以及局部变量。在函数完成执行,系统自行释放栈区内存,不需要用户管理。整个程序的栈区的大小可以在编译器中由用户自行设定,VS中默认的栈区大小为1M,可通过VS手动更改栈的大小。64bits的Linux默认栈大小为10MB,可通过ulimit -s临时修改。

静态存储区:

静态存储区内的变量在程序编译阶段已经分配好内存空间并初始化。这块内存在程序的整个运行期间都存在,它主要存放静态变量、全局变量和常量。
注意:

  1. 这里不区分初始化和未初始化的数据区,是因为静态存储区内的变量若不显示初始化,则编译器会自动以默认的方式进行初始化,即静态存储区内不存在未初始化的变量。
  2. 静态存储区内的常量分为常变量和字符串常量,一经初始化,不可修改。静态存储内的常变量是全局变量,与局部常变量不同,区别在于局部常变量存放于栈,实际可间接通过指针或者引用进行修改,而全局常变量存放于静态常量区则不可以间接修改。
  3. 字符串常量存储在静态存储区的常量区,字符串常量的名称即为它本身,属于常变量。
  4. 数据区的具体划分,有利于我们对于变量类型的理解。不同类型的变量存放的区域不同。后面将以实例代码说明这四种数据区中具体对应的变量。

代码区:

存放程序体的二进制代码。比如我们写的函数,都是在代码区的。

示例:

int a = 0;//静态全局变量区
char *p1; //编译器默认初始化为NULL
void main()
{
    int b; //栈
    char s[] = "abc";//栈
    char *p2 = "123456";//123456在字符串常量区,p2在栈上
    static int c =0; //c在静态变量区,0为文字常量,在代码区
    const int d=0; //栈
    static const int d;//静态常量区
    p1 = (char *)malloc(10);//分配得来得10字节在堆区。
    strcpy(p1, "123456"); //123456放在字符串常量区,编译器可能会将它与p2所指向的"123456"优化成一个地方
}

以上所有代码,编译成二进制后存放于代码区,文字常量存放于代码区,是不可寻址的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 01 "我觉得他一点也不好。" 小希一边吐槽,一边抹眼泪。问她干嘛,原来,小希想要报个插画班。 小希网上来回看了几...
    小小在隐身阅读 860评论 0 0
  • 读书得到了什么呢? 读书有目的吗?要带着目的去读书吗?带着目的读书的感觉是怎么样的? 好多人推荐说看哪些书可以锻炼...
    俺只念木石前盟阅读 377评论 0 2
  • 事件:接儿子练琴回家后,他说他要休息10分钟才做作业,而且边休息边看电视 行为:有点催促他 应对姿态:打岔 感受:...
    忆秦YQ阅读 199评论 0 0