Authors: | Kenneth Lee |
---|---|
Version: | 0.1 |
Date: | 2022-10-05 |
Status: | Draft |
这一个小节我们来看看C/C++的内存位置在什么地方,理解一下教科书中说的“堆”,“ 栈”,“数据”,“常量”这些数据都放在哪里。
我们说了,我们把一个程序从源代码编译成二进制,运行的时候,操作系统把二进制搬到 内存中。这个过程有不少细节,我们从一个程序看起:
int a;
int b = 3;
char * c = "hello";
void test(void) {
int i = 3;
static int j = 100;
}
int main(void) {
int d;
int e = 10;
char * f = "world";
char * g = malloc(100);
static int h = 10;
test();
}
这个程序中,我们有很多的变量,当我们编译成二进制的时候,二进制里面必须留着所有 这些信息,到时操作系统把这个文件搬到内存中,才能保持这个信息。
我们给它画张图:
a, b, c都是全局变量,所以我们都放在文件中了,里面的内容必须就已经有值了,所以 我们得放到二进制文件中。但main和test这两个函数,如果不调用,我们也不需要分配内 存,所以,这个二进制不到运行,里面都没有main和test函数里面数据的内存,但静态变 量是个例外,函数中的静态变量表示所有函数都用这个内存,所以它们就和全局变量一样 放,其他的都是运行的时候才需要决定用什么内存的。
Note
在实际中,其实g++还会把初始化过的和没有初始化过的全局变量分开放,这是为了 它自己管理的方便,这一点我们先忽略。
现在我们把这个二进制程序运行起来,搬到内存中,就是这样的:
可以看到,整个二进制里面的内容都被搬到内存中了,然后就是多了两个区,一个叫堆, 一个叫栈,堆用来放你运行的时候要求分配的内存,比如你调用malloc,说要100个字节 ,总得给你找个地方,这整个地方就叫堆。类似一个仓库,找到一个空闲的地方就给你, 你不用了就给别人,所以这个位置在哪里,就看怎么用这个仓库了。
栈不一样,栈好像一个垒起来的一叠纸,你要不放东西到顶上,或者从顶上拿走,反正你 不能从中间抽走一段。在我们上面这个程序中,你先调用main,main要d,e,f,g四个变量, 它就先占了栈最底部的空间,然后你调用test,test要i一个变量,它就占用d,e,f,g之 后的空间,等test返回了,这个i就可以不要了,你回到main,继续用那4个变量,反正i没 有用完,d, e,f,g肯定是不会被放弃的,这就是栈的区域。
这也是为什么全局变量你不需要初始化也能用,因为在二进制的时候,都已经给你一个值 了,堆栈变量是运行的时候临时找出来给你的,你不初始化,原来那个内存里面留着什么 值,它就是什么值,这就很随机了。