一个简单的空间分配的问题

好运萝 2019-01-09 11:17:14
今天瞎捣鼓遇到的一个问题
例如有如下场景

char *message(int i, int j)
{
char buff[1024] = "";
sprintf(buff, "%d + %d = %d", i, j, i + j);
return buff;
}

void main()
{
printf("%s", message(1, 2));
}


这时候 编译器会报warning C4172: 返回局部变量或临时变量的地址: buff
去查了以下这个warning 是因为在message内 buff为局部变量 返回局部变量的指针很不安全
https://bbs.csdn.net/topics/39064418

解决方法一个是 将buff作为参数返回而不是返回值,另一个就是将buff分配在栈上再加以管理
可是这么一个字符串可能用到的也不多 也许只是展示以下 就可能只是printf看一下 难道还要再去自己delete他吗 感觉好麻烦啊
一般都是怎么解决的
...全文
2571 52 打赏 收藏 转发到动态 举报
写回复
用AI写文章
52 条回复
切换为时间正序
请发表友善的回复…
发表回复
flybirding10011 2019-04-29
  • 打赏
  • 举报
回复
引用 33 楼 <span style="color:#4788C7">独孤由过</span>的回复:
[quote=引用 32 楼 lin5161678 的回复:] [quote=引用 31 楼 独孤由过 的回复:] 那是你无法判断而已
你能判断?? 你确定vs下 就栈空间就不会被覆盖? 确定吗?[/quote] 自己多尝试吧[/quote]<br />呵呵 缺心眼
Happy_Enger 2019-01-11
  • 打赏
  • 举报
回复
哈哈,你为什么不把printf放进message,在main里直接调用massage呢?
xiaoxiangqing 2019-01-11
  • 打赏
  • 举报
回复
这种报警本来就是正确的
尛破孩 2019-01-11
  • 打赏
  • 举报
回复
新手报到,一起学习
lin5161678 2019-01-10
  • 打赏
  • 举报
回复
引用 40 楼 @风轻云淡_ 的回复:
我虽然不认同他说的,但是vs下(win7_64+vs2015)如果用puts的话,确实可以输出值(已多次测试),上图:

win7_64+vs2015
打开release 并在配置属性 C/C++ 优化中 关闭内联函数扩展 如图

2次输出都不能输出123

打开release 并在配置属性 C/C++ 优化中 启用内联函数扩展
两次输出都是 123

对栈数据被覆盖的时间点进行假设的想法 非常稚嫩
基本处于没实际工作经验的学习阶段
对程序分析完全基于debug模式的编译结果

实际编程中 编译器优化做了非常多的工作
甚至 会把你整个函数调用的操作完全优化掉
就是说 你代码里面调用了函数
实际汇编里面 根本看不见函数调用
连栈内存分配操作都没有
更别提什么栈数据覆盖了

@风轻云淡_ 2019-01-10
  • 打赏
  • 举报
回复
引用 39 楼 lin5161678 的回复:
[quote=引用 38 楼 独孤由过 的回复:]
前面已经说了,自己多尝试,记得弄清楚原理
没空跟你这种自以为是,挖墙脚,曲解意的人说话

所以 扯半天 一句有用的话的都说不出来

自称原理是 栈空间没被覆盖
问依据是什么 不知道
自称 能确定栈空间没被覆盖
问是怎么确定 不知道

啧啧


[/quote]

我虽然不认同他说的,但是vs下(win7_64+vs2015)如果用puts的话,确实可以输出值(已多次测试),上图:

Ali AlNaghmoush 2019-01-10
  • 打赏
  • 举报
回复
这个厉害了,受益匪浅啊
kqtjhpl 2019-01-10
  • 打赏
  • 举报
回复
都是高手,学习了
好运萝 2019-01-10
  • 打赏
  • 举报
回复
提出这个问题的时候我确实已经根据以前的贴子得到了一些答案
那就是分配在堆上 这种方法我觉得在函数内分配有时候会忘了去delete掉
增加参数 这种我是想尽量减少参数
还有一个静态的方法这个是我之前不知道的
问这个问题 其一是想看看各位平时怎么用的 比较一下这些方法的优劣
第二也是想看一下有没有新的方法 和遗漏的地方 例如#10用的智能指针...
我翻到最后稍微有点庆幸不是所有人都用这个方法去做的 不然我怕是连看都看不懂了... 这当然也是一个解决方法但是奈何目前修为不够啊

理性的讨论我觉得还是很有意义的 就像上面两位兄弟在讨论局部变量栈内存会不会覆盖.... 拿出依据支撑自己的观点 就行了
不用强迫别人接受自己的观点(无论对错)
赵4老师 不愧是老油条 不跟你多BB 不如我们来问问神奇的海螺

xiaohuh421 2019-01-10
  • 打赏
  • 举报
回复
规则就是如此, 不要返回函数栈内临时变量地址. 如果你非要打破这个规则, 那也没办法. 如果你仅是打印, 那么就是函数内打印. 如果格式化出来有用, 那么就老实的按规则来. 参数 , 静态, new都可以
@风轻云淡_ 2019-01-10
  • 打赏
  • 举报
回复
引用 41 楼 lin5161678 的回复:
[quote=引用 40 楼 @风轻云淡_ 的回复:]
我虽然不认同他说的,但是vs下(win7_64+vs2015)如果用puts的话,确实可以输出值(已多次测试),上图:

win7_64+vs2015
打开release 并在配置属性 C/C++ 优化中 关闭内联函数扩展 如图

2次输出都不能输出123

打开release 并在配置属性 C/C++ 优化中 启用内联函数扩展
两次输出都是 123

对栈数据被覆盖的时间点进行假设的想法 非常稚嫩
基本处于没实际工作经验的学习阶段
对程序分析完全基于debug模式的编译结果

实际编程中 编译器优化做了非常多的工作
甚至 会把你整个函数调用的操作完全优化掉
就是说 你代码里面调用了函数
实际汇编里面 根本看不见函数调用
连栈内存分配操作都没有
更别提什么栈数据覆盖了

[/quote]
原来如此,学习了。
sichuanwww 2019-01-10
  • 打赏
  • 举报
回复
返回对象(string 产生拷贝) 或 返回静态变量,
最好不要返回局部分配空间。
weixin_44481836 2019-01-10
  • 打赏
  • 举报
回复
inet_ntoa
The Windows Sockets inet_ntoa function converts an (Ipv4) Internet network address into a string in Internet standard dotted format.

char FAR * inet_ntoa (
struct in_addr in
);

Parameters
in
[in] A structure that represents an Internet host address.
Remarks
The inet_ntoa function takes an Internet address structure specified by the in parameter and returns an ASCII string representing the address in ".'' (dot) notation as in "a.b.c.d''. The string returned by inet_ntoa resides in memory that is allocated by Windows Sockets. The application should not make any assumptions about the way in which the memory is allocated. The data is guaranteed to be valid until the next Windows Sockets function call within the same thread, but no longer. Therefore, the data should be copied before another Windows Sockets call is made.

Return Values
If no error occurs, inet_ntoa returns a char pointer to a static buffer containing the text address in standard ".'' notation. Otherwise, it returns NULL.

QuickInfo
Windows NT: Yes
Windows: Yes
Windows CE: Use version 1.0 and later.
Header: Declared in winsock2.h.
Import Library: Link with ws2_32.lib.

See Also
inet_addr
Mcdull丶Pig 2019-01-10
  • 打赏
  • 举报
回复
我是来看看 能不能获取积分的
oLuXian 2019-01-10
  • 打赏
  • 举报
回复
学习学习
  • 打赏
  • 举报
回复
引用 10 楼 Slzde_sub 的回复:



都快c++20了还妄图用static解决返回临时变量的问题?


返回一个std::unique_ptr<> 不就好了

大致代码长这样




std::unique_ptr<char*> message(int i, int j)
{
std::unique_ptr<char* > pBuff(new char[size]);
//operation
return std::move(pBuff);
}

正解。都这个时候了还有人不用智能指针🐎
weixin_44477993 2019-01-10
  • 打赏
  • 举报
回复
回复有积分的吗
独孤过 2019-01-09
  • 打赏
  • 举报
回复
这种在调用返回时使用不会出现问题,因为栈中临时字符数组还未被释放,但是在printf执行完之后不可再用 当然,不同编译和运行环境对栈管理策略可能不同,届时可能遇到一些问题
好运萝 2019-01-09
  • 打赏
  • 举报
回复


引用 2 楼 lin5161678 的回复:
char *message(int i, int j,char* buff)
{
sprintf(buff, "%d + %d = %d", i, j, i + j);
return buff;
}

int main()
{
char buff[1024];
printf("%s", message(1, 2, buff));
}


也就是 还是要增加参数 但是写成返回值类型定义成char *不就是为了减少这个参数的吗...还是我对返回类型的理解有误...
lin5161678 2019-01-09
  • 打赏
  • 举报
回复
char *message(int i, int j,char* buff)
{
sprintf(buff, "%d + %d = %d", i, j, i + j);
return buff;
}

int main()
{
char buff[1024];
printf("%s", message(1, 2, buff));
}

加载更多回复(33)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧