笔试之内存分配问题

 

需要知道的概念:

  1、程序:包括代码和数据,是静态的概念

  2、进程:程序的执行过程,是指一个程序中的代码在一个数据集合中的运行过程,所以说相同代码在不同的数据集合上运行,乃至在同样的数据集合上的多次运行都是不同的进程。进程是一个动态概念

  3、线程:可以理解为进程中的一个代码片段的执行。故常说一个进程包含多个线程,多个线程共享数据空间。操作系统不会单独为线程分配资源(存储空间)

  程序是静态的,进程是动态的;进程是操作系统分配资源的最小单位,线程是操作系统调度的最小单位。

  一个程序在运行起来以后,就成为的进程,此时操作系统要为该进程分配虚拟存储空间,这个存储空间就包括了:栈区(stack),堆区(heap),全局区(静态区)(static),文字常量区,代码区。至于这些存储区的使用情况,就取决于我们程序员的代码实现了!举例说明:

  栈区(stack):人们说:栈区是由编译器自动分配的,我认为这种说法是不准确的,只是说在编译阶段,栈区的分配情况就已经是确定好了的(也就是不管进程的接收参数如何,或是执行多少次,栈区变量一定是那样一个地址),毕竟内存的分配是由操作系统内核的内存管理机制来完成的。OK!不钻牛角,就说是编译器在编译时分配。我的理解是:在编译阶段,编译器会根据代码中变量的定义情况,依据字节对齐原理进行分配(具体方法会在后续的《栈区内存分配详解》中介绍)。但要注意,进程的执行进入函数体以后(自动变量所在的函数体),变量才和栈区地址对应起来了,这时&a(a是一个栈区变量)才是有值的,但这个时候变量不能使用,其值可能是一个不确定数。当程序运行到达该变量的定义语句时,作用域开始,并且变量中有了确定的值,当函数体结束,作用域结束,空间有操作系统回收。

  堆区(heap):堆区是由程序员分配释放的。我的理解是:堆区是进程执行过程中,由操作系统根据进程的运行情况,动态分配的;释放和回收需要程序员写代码来实现,而不是自动回收。

  这就解释了为什么,int a[n]--这样的栈区数组定义方式有错,因为在编译阶段,程序没有运行,故不知道变量n的值为多少,所以产生错误!!而动态分配的存储空间就可以这样定义 int *p = new a[n],因为动态分配存储空间是堆上分配,属于运行时分配,程序运行到动态分配存储空间这条语句时,n的值已经计算出来了。而且不同的运行过程,或是多次执行,n的值可能不一样(例如进程的接收参数不同),也就是空间大小也就不一样,操作系统需要在堆区二叉树中寻找一个满足该大小的空间,所以起始地址也会不一样。再次印证了动态的含义。

  全局(静态)区:1.全局变量:编译阶段 由编译器分配(确定)地址,但是在进程开始时才与该地址对应,但此时变量有一不确定值,处于不可使用状态,一直到改全局变量的定义语句,作用域开始,一直到进程结束。2.static静态变量:在整个进程过程中,只能被赋初值一次。

  文字常量区:用于存放常量字符串。

  代码区:存放程序的二进制代码。

 示例:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int a = 0; /*全局区*/
 5 char *p;  /*全局区*/
 6 
 7 int main(void)
 8 {
 9     int b = 10;  /*栈区*/
10     char s[] = "abc";  /*abc在常量区,s在栈区*/
11     char *p1;  /*栈区*/
12 
13     static int c = 0; /*全局(静态区)*/
14     
15     p = (char*)malloc(b);  /*变量p在全局区,指向的分配得来的b个存储空间在堆区*/
16     p1 = new char[b];   /*变量p1在栈区,指向的分配得来的b个存储空间在堆区*/
17     return 0;
18 }

 

 

 

posted @ 2012-10-20 15:54  Go ahead!  阅读(316)  评论(0编辑  收藏  举报