zoukankan      html  css  js  c++  java
  • C/C++的四大内存分区 分类: C/C++ 2015-05-09 01:36 163人阅读 评论(0) 收藏


    导读

    正确的理解C/C++程序的内存分区,是合格程序猿的基本要求。
    网络上流形两大版本内存分区,分别为:

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

    且不论以上两种分区孰是孰非,孰优孰劣,我认为具体的内存分区和编译器有很大关系,我想不同编译器对内存的划分都不尽相同,但也大同小异。
    综合对比,查阅相关资料,提出自己对C/C++程序的内存分区的认识。可划分为四大内存分区:堆、栈、静态存储区和代码区。

    堆区:
    由程序猿手动申请,手动释放,若不手动释放,程序结束后由系统回收,生命周期是整个程序运行期间。使用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"优化成一个地方
    }

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


    总结

    在理解C/C++内存分区时,常会碰到如下术语:数据区,堆,栈,静态存储区,静态区,常量区,常变量区,全局区,字符串常量区,静态常量区,静态变量区,文字常量区,代码区等等,初学者被搞得云里雾里。在这里,尝试捋清楚以上分区的关系。
    数据区包括:堆,栈,静态存储区。
    静态存储区包括:常量区(静态常量区),全局区(全局变量区)和静态变量区(静态区)。
    常量区包括:字符串常量区和常变量区。
    代码区:存放程序编译后的二进制代码,不可寻址区。

    可以说,C/C++内存分区其实只有两个,即代码区和数据区。

    本文难免出错,请同仁留言批评指正!谢谢


    参考文献

    [1]http://www.cnblogs.com/BreakMind/archive/2011/11/30/2268671.html

    版权声明:本文为博主原创文章,未经博主允许不得转载。

    ---转载或者使用代码,请注明原作者 This is bill
  • 相关阅读:
    129 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 02 懒汉式的代码实现
    128 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 01 饿汉式的代码实现
    127 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 02 单例模式概述 01 单例模式的定义和作用
    126 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 01 设计模式概述 01 设计模式简介
    125 01 Android 零基础入门 02 Java面向对象 05 Java继承(下)05 Java继承(下)总结 01 Java继承(下)知识点总结
    leetcode-----121. 买卖股票的最佳时机
    leetcode-----104. 二叉树的最大深度
    Json串的字段如果和类中字段不一致,如何映射、转换?
    Mybatis-Plus的Service方法使用 之 泛型方法default <V> List<V> listObjs(Function<? super Object, V> mapper)
    模糊查询
  • 原文地址:https://www.cnblogs.com/ScytheWH/p/4622974.html
Copyright © 2011-2022 走看看