关于C语言内存方面的话题要真说起来的话那恐怕就没头了,所以本文仅仅是一个浅谈。关于内存问题不同平台之间有一定的区别。本文所指的平台是x86的Linux平台。
用C语言做程序(其实其他语言也一样),不仅要熟悉语法,其实很多相关的背景知识也很重要。在学习和研究C语言中内存分配的问题前,首先要了解一下Linux分配给进程(运行中的程序)的地址空间是什么样的。
总的来说有3个段,即代码段,数据段和堆栈段(学过汇编的朋友一定很熟悉了)。
代码段就是存储程序文本的,所以有时候也叫做文本段,指令指针中的指令就 是从这里取得。这个段一般是可以被共享的,比如你在Linux开了2个Vi来编辑文本,那么一般来说这两个Vi是共享一个代码段的,但是数据段不同(这点 有点类似C++中类的不同对象共享相同成员函数)。
数据段是存储数据用的,还可以分成初始化为非零的数据区,BSS,和堆(Heap)三个区域。初始化非 零数据区域一般存放静态非零数据和全局的非零数据。BSS是Block Started by Symbol的缩写,原本是汇编语言中的术语。该区域主要存放未初始化的全局数据和静态数据。还有就是堆了,这个区域是给动态分配内存是使用的,也就是用 malloc等函数分配的内存就是在这个区域里的。它的地址是向上增长的。
最后一个堆栈段(注意,堆栈是Stack,堆是Heap,不是同一个东西),堆 栈可太重要了,这里存放着局部变量和函数参数等数据。例如递归算法就是靠栈实现的。栈的地址是向下增长的。具体如下:
========高地址
程序栈 堆栈段
向下增长
“空洞” =======
向上增长
堆
------ 数据段
BSS
------
非零数据
=========低地址 =======
========= =======
代码 代码段
========= =======
需要注意的是,代码段和数据段之间有明确的分隔,但是数据段和堆栈段之间没有,而且栈是向下增长,堆是向上增长的,因此理论上来说堆和栈会“增长到一起”,但是操作系统会防止这样的错误发生,所以不用过分担心。
有了以上理论做铺垫,下面就说动态内存的分配。上面说了,动态内存空间是在堆中分配的。实现动态分配的也就是下面几个函数:
stdlib.h :
void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
一个一个说吧。
基本就这些了,这些都是比较基础的话题,高级话题和细节问题还有很多,这里就不进行说明了。