c/c++内存分区


导读

正确的理解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)数据区的具体划分,有利于我们对于变量类型的理解。不同类型的变量存放的区域不同。后面将以实例代码说明这四种数据区中具体对应的变量。

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

示例代码:

<code class="language-C++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//静态全局变量区</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> *p1; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//编译器默认初始化为NULL</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> main()
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//栈</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> s[] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"abc"</span>;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//栈</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> *p2 = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"123456"</span>;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//123456在字符串常量区,p2在栈上</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> c =<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//c在静态变量区,0为文字常量,在代码区</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> d=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//栈</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> d;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//静态常量区</span>
    p1 = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> *)<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">malloc</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//分配得来得10字节在堆区。</span>
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strcpy</span>(p1, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"123456"</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//123456放在字符串常量区,编译器可能会将它与p2所指向的"123456"优化成一个地方</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

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


总结

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

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



为了帮助网友解决“C++文字常量是什么,是常量吗”相关的问题,中国学网通过互联网对“C++文字常量是什么,是常量吗”相关的解决方案进行了整理,用户详细问题包括:RT,我想知道:C++文字常量是什么,是常量吗,具体解决方案如下:

解决方案1:
代码区是什么,是存放整个程序的字面文件?那不就是.CPP?

解决方案2:
C/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) - 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)-一全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后有系统释放。 4、文字常量区 -一常量字符串就是放在这里的。程序结束后由系统释放。 5、程序代码区-一存放函数体的二进制代码。 文字常量区是指程序中只读不可写的常量数值和字符串,是包含常量的。 代码区存储二进制代码,注意可执行文件中的程序是编译器编译出来的,机器可以直接运行的机器码,本质上就是一系列二进制数。计算既可以直接执行的都是二进制码,而CPP文件是包含未经过编译的文本格式的源程序,是不能由计算机直接运行的。 也就是说可执行文件是由源程序CPP文件以及一些其他必要的工程文件编译而成的,二者的内容实际完全不同,一个是二进制格式,一个是文本格式。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值