C语言函数返回指针的问题
自我们开始学习C语言中的指针,老师就说返回函数局部变量的地址是没有意义的,因为函数调用完毕,系统回收函数中用到各种资源,函数栈顶指针向高位地址移动。指针指向的内容已经被释放,返回的指针会指向不可预料的内容。
我们可以从C程序的内存布局讲起(详细内容,请查看超链接内容,本片文章只会讲解与本篇文章相关的内容)。
C语言的内存布局具体可以分为五部分:
- 栈(stack):是一个先进后出的数据结构,和函数调用相关(函数中的局部变量存储在该部分),栈是由高地址向低地址增长(向下增长),栈的底部存放着命令行参数和环境变量。
- 我们可以这样简单的理解C程序执行过程,main(int argc, char *argv)函数先入栈,栈顶指针下移,遇到其他函数调用,该函数进栈,栈顶指针下移,直到再也没有其他函数调用时,函数返回,栈顶指针上移,并且释放被调函数所占用的资源(包括局部变量),直到main(int argc, char *argv) 返回,程序执行完毕,操作系统回收资源。
- 堆(heap):是用户自己管理的内存部分,可以通过 malloc()、realloc()和 free()进行管理。堆是从低地址向高地址增长。
- 申请的内存空间一定要释放,否则会造成内存泄漏。
- 用户自己申请的内存空间在free之前都会一直存在。(所以函数可以返回自己在堆上申请的内存地址)
- Uninitialized Data Segment:用于存放用户未初始化的全局变量和静态局部变量。(但是编译器会默认全部初始化为0)
- Initialized Data Segment:用于存放用户已经初始化的全局变量和静态局部变量
- 程序代码区(Text):用来存放可执行代码。
那么函数可以返回哪些变量的指针呢?
- 存储在 Uninitialized Date Segment 和 Initialized Data Segment都具有静态存储周期,即在程序执行期间一直存在。所以函数可以返回全局变量和静态局部变量的指针;
- 函数可以返回自己在堆上动态分配的内存的地址,只要这块内存未被free()释放即可。
还有一种特殊情况:
函数的参数本身就是指针变量,函数最后返回了参数,由于参数是由主调函数完成初始化,并且函数返回值指向主调函数的一个变量,所以不会产生问题。
(如有错误,欢迎指正!)
种一棵树最好的时间是十年前,其次是现在。