博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数返回局部变量的一些问题
阅读量:6155 次
发布时间:2019-06-21

本文共 2881 字,大约阅读时间需要 9 分钟。

hot3.png

    函数里面的局部变量只是在函数里面,一旦函数执行完毕,(栈)局部变量的内存就会被释放掉(堆需要程序猿手动释放)。如果我们返回是值,那么函数会将局部变量值copy并返回。如果是指针,那么函数就会直接返回指针,如果在这种情况下调用,就会出现错误,因为内存已经被释放了。下面一一来举例说明这个问题。

1. 直接值返回(RIGHT)

#include
using namespace std;int myfoo(){        int a = 8;        return a;}int main(){        int a = myfoo();        cout << "return is " << a << endl;}

这个写法是没有问题的,myfoo执行完之后a的内存会被释放掉,函数会拷贝a的值并返回,所以主函数的a和myfoo里面的a不是同一个地址。

(gdb) p &a$15 = (int *) 0x7fffffffe58c(gdb) p a$16 = 8(gdb) p &a$17 = (int *) 0x7fffffffe5ac(gdb) p a$18 = 8

通过gbd可以看到函数体里面的a的地址和返回结果的a的地址是不一样的。

2. 直接返回字符串常量(RIGHT)

#include
using namespace std;char* myfoo(){        char* a = "hello, I'm string constant";        return a;}int main(){        char* a = myfoo();        cout << "return is " << a << endl;}

在这个例子中,"hello, I'm string constant"是一个字符串常量,存在文字常量区。函数会讲字符串首地址返回,那么在主函数里面也可以直接使用。

$ g++ -g char.cpp  -o charchar.cpp: In function ‘char* myfoo()’:char.cpp:6:12: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

编译会报警,从字符串常量转换成char*

通过gbd来查看内存地址,可以看出二者内存地址都是0x40095c

(gdb) p a$2 = 0x40095c "hello, I'am string constant"main () at char.cpp:1313cout << "return is " << a << endl;(gdb) p a$3 = 0x40095c "hello, I'am string constant"

3. 返回栈局部指针(WRONG)

#include
using namespace std;char* myfoo(){        char a[] = "hello, I'm char local";        return a;}int main(){        char* a = myfoo();        cout << "return is " << a << endl;        return 0;}

这个case是非法的。myfoo里面的a是一个栈局部变量,函数执行完毕,a的内存会被释放掉,如果在主函数里面直接使用会报错。

$ g++ char_local.cpp  -g -o char_localchar_local.cpp: In function ‘char* myfoo()’:char_local.cpp:6:7: warning: address of local variable ‘a’ returned [enabled by default]

gcc编译则会报警,显示是一个局部变量,其实看到这个,我们就知道我们代码有问题。在通过gdb进一步查看。

(gdb) p &(a[0])$2 = 0x7fffffffe570 "hello, I'm char local"(gdb) p a$3 = 0x7fffffffe570 "\200B\255\367\377\177"

&(a[0])就是取字符串首字符的地址,可以看到在myfoo里面是有值的,但是在main函数里面,可以看到内存已经被释放了。变成空了。

4. 返回堆局部指针(RIGHT)

#include
#include
#include
#include
using namespace std;char* myfoo(){        char *a = (char*)malloc(100);        strncpy(a, "hello, I am malloc", 100);        return a;}int main(){        char* a = myfoo();        cout << "return is " << a << endl;        return 0;}

通过malloc申请的变量在堆区,需要程序员自己释放(也是内存泄露的原因之一),myfoo执行完了,内存没有被释放,所以这样使用不会有问题。

(gdb) p a$1 = 0x602010 "hello, I am malloc"(gdb) p a$2 = 0x602010 "hello, I am malloc"

可以看到myfoo和main里面的地址都是一样的。

5. 返回静态变量(RIGHT)

#include
using namespace std;char* myfoo(){        static char a[] = "hello, I'm static";        return a;}int main(){        char* a = myfoo();        cout << "return is " << a << endl;        return 0;}

static变量作用域是全局,所以肯定没问题。直接gdb查看可以验证。

(gdb) p &(a[0])$2 = 0x601050 "hello, I'm static"(gdb) p a$3 = 0x601050 "hello, I'm static"

转载于:https://my.oschina.net/jungleliu0923/blog/194208

你可能感兴趣的文章
判断IP地址是否合法类
查看>>
linux 常用命令
查看>>
python 中的input
查看>>
Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) D. Little Artem and Dance 模拟
查看>>
SSL延迟有多大 (Https)
查看>>
const constexpr C++ 解释
查看>>
zookeeper leader选举机制
查看>>
Java 反射机制[Field反射]
查看>>
深入理解Delete(JavaScript)
查看>>
JS 借助 pako.js 实现网络请求获取 gzip 数据流并解析, 解决汉字乱码
查看>>
28.Node.js 函数和匿名函数
查看>>
python练习笔记——分解质因数
查看>>
课程三(Structuring Machine Learning Projects),第二周(ML strategy(2)) —— 0.Learning Goals...
查看>>
远程桌面时提示凭证不工作问题的终极解决办法
查看>>
支付系统整体设计:整体架构设计以及注意要点(一)
查看>>
Eclipse安装zylin[转]
查看>>
自己动手写js分享插件 [支持https] (QQ空间,微信,新浪微博。。。)
查看>>
[UWP]针对UWP程序多语言支持的总结,含RTL
查看>>
并发工具类(三)控制并发线程数的Semaphore
查看>>
Objective-c的@property 详解
查看>>