warning: function returns address of local variable【函数返回首地址出错原因】

warning: function returns address of local variable【解决函数返回首地址出错】

1- 报错展示

这个提示就是告诉我,我定义的这个tmp_data这个是局部变量(在自定义函数里面定义的),不能返回他的地址,返回给主函数地址没用的,因为我这个函数用完就释放啦,你拿着我的地址找不到我的啊!~
在这里插入图片描述
对比分析更好理解:

311行自定义函数返回结构体中的 buf (首地址)失败。

304 char* get_first_data(sqlite3 *db)
305 {
306         package tmp_data;
307         int rc = -1;
308         char *sql_select;
309         sql_select = "select *from temper limit 1";
310         rc = sqlite3_exec(db, sql_select, callback, &tmp_data, NULL);
311         return tmp_data.sed_del_buf;
312 }

但是286行能够返回结构体中int类型的数据。

279 int get_line_count(sqlite3 *db)
280 {
281         package tmp_count;
282         int rc = -1;
283         char *sql_count;
284         sql_count = "select count(*) from temper";
285         rc = sqlite3_exec(db, sql_count, callback_count, &tmp_count, NULL);
286         return tmp_count.count;
287 }

结构体:

typedef struct
{
        char sed_del_buf[512];
        int  count;
}package;

在这里插入图片描述

先找原因:
在c程序内存布局中可以知道,我们自定义的函数中的局部变量都是存放在栈区的,并且是自动分配,{}有效,离开后{}中自动释放。上述两个函数中我都是在函数内定义的结构体变量。导致这个结构体变量在函数用完之后就释放了。函数返回后该函数的栈空间消失,所以函数中返回局部变量的地址都是非法的。因为人家消失了,你凭借地址是找不到的。
上述中结构体变量都是在函数内声明的,所以创建的结构体变量就是局部变量,返回结构体的值的时候其实是返回结构体,没有返回结构体的地址;如果返回结构体的地址,就是错误的。

回到问题:
我们返回数值,那肯定可以啊,传过去那边就接收到了,实实在在的数据
我们返回地址,那边可以收到,但是这个地址指向的内容已经被清理了,咋搞?所以指向的内容啥都没有,就是NULL,会提示错误,但是可以运行,只是啥都没有
所以可以获取结构体中int类型的数据,但是不能获取地址,因为地址指向的内容已经消亡了,如下结果:
在这里插入图片描述

2- malloc开辟空间解决

C语言内存布局中我们看到在堆区是可以利用malloc自己来管理内存的,用完释放掉就可以了,于是我们利用malloc来解决。
简单来说,malloc函数的作用是开辟一个空间来给你使用,用完free就可以了。
这个方法适合返回的内容是改变的,每次调用函数返回的内容都不一样。
第306行malloc分配空间:

304 char* get_first_data(sqlite3 *db)
305 {
306         package *tmp_data = (package*)malloc(sizeof (package));
307         int rc = -1;
308         char first_data_buf[512];
309         char *sql_select;
310         sql_select = "select *from temper limit 1";
311         rc = sqlite3_exec(db, sql_select, callback, tmp_data, NULL);
312         return tmp_data -> sed_del_buf;
313 }

成功执行:
在这里插入图片描述

3- static静态局部变量解决

函数的返回值可以是一个static类型的局部变量的地址。
如果你返回的内容是不变的,就可以用这个方法。
所以在306行定义结构体变量的时候定义为静态局部变量尝试,每次获取到的数值都是一样的,这是因为静态局部变量赋初值是在编译时进行值的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。

304 char* get_first_data(sqlite3 *db)
305 {
306         static package tmp_data;
307         int rc = -1;
308         char *sql_select;
309         sql_select = "select *from temper limit 1";
310         rc = sqlite3_exec(db, sql_select, callback, &tmp_data, NULL);
311         return tmp_data.sed_del_buf;
312 } 

在这里插入图片描述

总体就是这样,理解还是不怎么到位,还需要慢慢加深~

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值