C语言内存分配及函数返回值的解析。
C语言的内存分配主要如下:
(1)栈区:在执行函数时,函数内局部变量(不包含static变量)、函数返回值的存储单元在栈区上创建,
函数执行结束时这些存储单元自动被释放。栈区内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(2)堆区:即动态分配内存分配,程序在运行时用malloc(calloc,realloc等)申请的内存,程序员自己负责用free释放内存。
(3)静态存储区:该内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。此处存放全局变量、static变量。
(4)常量区:整型常量、浮点型常量、字符型常量及字符串常量都分配在文字常量区,程序结束后由系统释放。
(5)代码区:存放整个程序的代码。数据和代码是分开存储的。


如下有几种容易出错的情况:
下面简单分析一下。
对于子函数char* function()。
内部分配了
返回的是b。是一个指向指向字符的指针。
修改一下function()
这个很好解释。a是数组名,就是一个指针,是一个执行含有两个char元素的数组的指针。
但是传过去的还是一个字符。
再改一下:
看,并没有传过来,是因为return a 中的a是局部数组的首地址,它是栈区地址。funciton函数执行结束时组数a存储单元自动释放。所以不应该返回过去。如果想要正确返回组数a的地址,可以再定义数组时加static修饰或定义为全局变量。
看结果:
至今为止没有使用malloc。其实这个也可以达到这个结果。但是不能忘记free。
看如下程序:
不是说“函数执行结束时这些存储单元自动被释放。”么?
没关系我们再修改一下:
两个子函数,形参、返回值、函数体出了存储在静态区的常量不同其他都一样。
所以进入子函数时,系统为之分配的栈空间一样,再因为操作系统和编译器都一样。外部环境很相似。所以栈的地址区域和所有变量的分配地址都一样。
我们这里再说明一下:
(1)我们是在xp操作系统上运行的。是有MMU的。是有内存映射的。所以我们的地址这时都是虚拟地址,是操作系统为每一个
进程分配的4G的虚拟地址,通过内存映射这些地址会被映射到物理地址上。
(2)当第一个自函数退出时,为之分配的栈空间就会被释放。但并不是清零的操作,而是这块内存标明可以被使用,
在学习操作系统的过程中,还记得内存分配的。是沿着那个链表式的东西在找一块儿合适的内存空间。
被释放只是说明这块儿内存可以被重新分配。没有清空的操作,这个对比试验可以得出这个结果。
看程序:
子函数中初始化了一个字符数组,一个char指针,一个指向字符的char指针。结束前把这些局部变量的地址都传给了全局变量。
在主函数中,访问这些地址,都未成功。这是因为在函数结束后和打印变量之间还有其他函数的调用。所以,那块栈空间又被改写了。
注意,为了安全,在子函数中千万不要return 指针类型的局部变量值。栈内地址不能安全的传递到函数外。可以传,但是不安全,因为很肯能会改变。
- 1楼rohsuton昨天 08:56
- ”存储单元自动被释放“并不意味着存储单元的内容清空吧,这块内存没再次被使用的情况下可以使原来的数据吧
