静态分配和动态分配
静态分配和动态分配
在讲述这个之前我们分享一段程序,从这个程序中我们来思考下为什么,类似的程序最后的输出结果不一样:
调用第一个函数时,str指向的那块内存在函数返回时,被系统释放了。返回后的str什么都没有。最后输出的都是乱的。而调用第二个函数时,str指向的那块内存在函数返回时,竟然没被系统释放,最后在主函数中能够把str指向的内存里面的数据输出来。为什么第二个函数返回时,str指向的内存区域没被系统释放??为此下面引出本文我们要讲的主题—静态分配和动态分配。
静态分配-静态分配是编译器完成的,不能由程序员自动分配和释放。如局部变量的分配。 动态分配-动态分配我们可以在函数中任何时候定义分配并释放,并且由程序员分配释放,系统不会自动释放。动态分配的数据空间存放在堆中。上面的第二个函数中,char *str = "helllo"是在堆中分配内存,所以函数返回时,内存不释放。
c/c++程序占有的内存空间逻辑上分为四个部分:1、静态数据区 2、动态数据区 3、代码区 4、文字常量区
1、静态数据区-静态数据区也称之为全局区,全局变量和静态变量分配在静态数据区。初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
2、动态数据区-动态数据区包括栈区和堆。栈(stack)和堆(heap)是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。本地变量分配在动态数据区。下面对里面的栈区和堆区分别说明:
3、代码区-存放函数体的二进制代码。
4、文字常量区-常量字符串存储在这里,程序结束后由系统释放。
注意:在栈上所申请的内存空间,当我们出了变量所在的作用域后,系统会自动回收这些空间,而在堆上申请的空间,当出了相应的作用域以后,我们需要自己释放所申请的内存空间,如果我们不及时对这些空间进行释放,那么内存中的内存碎片就越来越多,从而我们的实际内存空间也就会变的越来越少。
下面给出C中的代码内存布局:
从上面我们可以明显看出栈是从高地址向低地址增长,堆是从低地址向高地址增长。
char* stackMalloc() { char str[] = "yelllo"; return str; } char* heapMalloc() { char *str = "helllo";// return str; } int main() { char *str = heapMalloc(); int i = 0; while(str[i] != " ")printf("字符串中的元素%c ", str[i++]); return 0; }
调用第一个函数时,str指向的那块内存在函数返回时,被系统释放了。返回后的str什么都没有。最后输出的都是乱的。而调用第二个函数时,str指向的那块内存在函数返回时,竟然没被系统释放,最后在主函数中能够把str指向的内存里面的数据输出来。为什么第二个函数返回时,str指向的内存区域没被系统释放??为此下面引出本文我们要讲的主题—静态分配和动态分配。
静态分配-静态分配是编译器完成的,不能由程序员自动分配和释放。如局部变量的分配。 动态分配-动态分配我们可以在函数中任何时候定义分配并释放,并且由程序员分配释放,系统不会自动释放。动态分配的数据空间存放在堆中。上面的第二个函数中,char *str = "helllo"是在堆中分配内存,所以函数返回时,内存不释放。
c/c++程序占有的内存空间逻辑上分为四个部分:1、静态数据区 2、动态数据区 3、代码区 4、文字常量区
1、静态数据区-静态数据区也称之为全局区,全局变量和静态变量分配在静态数据区。初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
2、动态数据区-动态数据区包括栈区和堆。栈(stack)和堆(heap)是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。本地变量分配在动态数据区。下面对里面的栈区和堆区分别说明:
(1)栈区(stack)
由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的,那么就把它想成数组,它的内存分配是连续分配的,即所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器会自动接着当前栈区的结尾来分配内存。栈是从高地址向低地址增长的。
(2)堆区(heap)
一般由程序员分配释放, 若程序员不释放,程序结束时可能由操作系统回收。类似于链表,在内存中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的.一旦某一节点从链中断开,我们要人为的把所断开的节点从内存中释放。堆是从低地址向高地址增长的。
注意:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。栈的动态分配和堆不同,它的动态分配是由编译器进行释放,无需我们手工实现。3、代码区-存放函数体的二进制代码。
4、文字常量区-常量字符串存储在这里,程序结束后由系统释放。
注意:在栈上所申请的内存空间,当我们出了变量所在的作用域后,系统会自动回收这些空间,而在堆上申请的空间,当出了相应的作用域以后,我们需要自己释放所申请的内存空间,如果我们不及时对这些空间进行释放,那么内存中的内存碎片就越来越多,从而我们的实际内存空间也就会变的越来越少。
下面给出C中的代码内存布局:
从上面我们可以明显看出栈是从高地址向低地址增长,堆是从低地址向高地址增长。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。