【内存分配系列】之进程内部内存分配(内存篇 第2节)

来源:互联网 发布:知父莫若子txt百度云 编辑:程序博客网 时间:2024/05/02 07:02

 

        上一节大致讲了下系统是如何为进程分配内存。那么一个进程得到了这4G空间后该怎么办呢?程序员可以使用全部内存么?答案是否定的。

        WINDOWS操作系统将地址范围4M-2G划分为用户地址空间,其余空间保留给系统之用或系统预留空间。还有一点请注意。每个进程分配时,内存地址都是从0~0xFFFFFFFF(4G)。A进程地址0X400000(4M)映射了可执行文件,而B进程的地址0X400000(4M)也映射了可执行文件。当然A和B映射的物理内存地址是不同的。这个差异由MMU来控制。至于进程在物理内存中的边界问题,很复杂,我没搞懂,不便发表言论,唯恐别人笑我SB,反正我知道是MMU提供的防止进程内存越界的技术。

        既然内存也分配好了,用户空间也划好了,那么进程内部怎么规划这些空间呢?

        C/C++编译的程序内存空间分为这么几种:

1、栈区(stack)——由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)——一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。
3、全局区(静态区 static)——全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
4、文字常量区——常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区——存放函数体的二进制代码。

        引用网上的一个例子。

//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456/0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456/0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

        我只讲个大概,函数的一些值类型数据都由系统分配在栈区。而堆区是由程序员自己分配。例如,C中,用malloc()函数进行内存分配。而释放用free()函数。不过看网上据说是不可以释放栈区内存。而C++中,可以用int *p;p=new int;来分配内存。至于释放,可以用delete p;我在考虑,那我删掉的只是个指针啊,嗯,似乎是这样的。那么我们有理由相信一点,系统只是用一个链表记录未被系统指向的内存,即所谓的空闲内存。但是如果内存空间被赋值了,即使你删了指针,那么内存的内容仍然没变。所以申请一块内存后,请先清空内存再使用。呵呵......

        通过这一节的介绍,你可能已经对进程内部如果规划内存有了一定了解,也知道了我们的一些数据具体放在那里了。我们每一个进程内部都是按上面这样分配的哦!呵呵,不要搞混。

        结构体作为一种重要的值类型,它的内存是如何分配的呢,它跟类又有哪些差别呢,请看下节:《【内存分配系列】之结构体和类内存分配(内存篇 第3节)》。

原创粉丝点击