这段代码为什么在 win 和 Linux 下结果不一样

2018-09-19 09:24:40 +08:00
 zynlp
#include <iostream>

using namespace std;

struct A{
    const char* a;
};

void f(A* a){
    string s("abc");
    a->a = s.c_str();
}

int main(int argc, char* argv[]){
    A a;
    f(&a);
    printf("a: %s\n", a.a);
    return 0;
}

这属于 ub 的问题吗?

4825 次点击
所在节点    C
25 条回复
zwzmzd
2018-09-19 09:27:26 +08:00
s 都随着函数 f 结束销毁了,再去用 c_str 本身就有问题
zynlp
2018-09-19 09:39:08 +08:00
@zwzmzd 嗯,但是 linux 下还是会有 abc 的输出...
ai277014717
2018-09-19 09:42:33 +08:00
编译器内部实现不一样造成的吧
seancheer
2018-09-19 09:46:13 +08:00
@zynlp 内存释放并不代表那块内存里面的内容会被写成 0,只是说这块内存可以被其他代码使用了。。你这个时候访问一块已经释放的内存虽然这会儿正常,但是不保证过一段时间还是正常的。。当程序规模比较大的时候,这块内存很有可能很快就被其他代码段使用了。

这就是传说中踩内存中的一种情况。
liangweijia6000
2018-09-19 09:49:13 +08:00
这是想研究啥。。
zivyou
2018-09-19 09:49:45 +08:00
会不会不同平台的垃圾清理方式不同导致的?比如 windows 中,在函数调用完之后,该函数的局部变量就被清理;而 Linux 将这个动作延迟到了进程退出(只是一种推测,我没有证实过)。
dynamicheart
2018-09-19 09:50:16 +08:00
@zynlp 在 Linux 下,离开 f 作用域后,s 被销毁了,a 指向的是一个无效的地址空间,但因为这段内存空间还没有被复用,里面的数据还是 abc,所以打印出来的是 abc。
zynlp
2018-09-19 09:51:12 +08:00
@seancheer 所以是 vs 里把这块内存给置 0,而 g++下没有置 0 的原因吗?
disk
2018-09-19 09:51:51 +08:00
别这样,vs 安全检查比较严格,你不知道什么时候悬空
wdlth
2018-09-19 09:55:07 +08:00
我在 Linux 下执行是返回乱码
ipwx
2018-09-19 10:02:55 +08:00
这是未定义行为吧,你去理解它没有意义。
Rosanta
2018-09-19 10:13:37 +08:00
UB 有啥好研究的,你开不一样的优化等级输出还不一样呢
rocbomb
2018-09-19 10:13:54 +08:00
想起了大一 C 语言课本上的 a=(i++)*(i++)*(i++)*(i++)*(i++)*(i++);
这种代码在工作中 谁写出来我非打死他不可
seancheer
2018-09-19 10:14:27 +08:00
@zynlp 不一定啊。。和具体实现相关。具体就要找下 vc 和 linux 下的实现区别了。不过个人觉得死磕这个没有意义。
你代码本身就是错误的行为,真正系统下是肯定会出问题的,无论 vc 还是 g++
sbw
2018-09-19 11:36:03 +08:00
学习一下 Rust 你就知道
boris1993
2018-09-19 12:47:49 +08:00
@rocbomb #13 这个........火刑柱伺候着
codehz
2018-09-19 12:51:23 +08:00
@rocbomb 把前面的 a 改成 i 更好(
429839446
2018-09-19 14:19:08 +08:00
请看 cppreference, c_str()这样用是未定义行为.
shilyx
2018-09-19 14:20:32 +08:00
一楼说得对,代码错了,这是前提。

错了的代码输出什么,只能回答:是什么就是什么,无任何保证。

你汇编跟踪以下,也能搞清楚为什么会那样输出,一句话,各有各的道理,编译器不背锅。
nutting
2018-09-19 14:29:24 +08:00
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16),编译不过去
Apple LLVM version 7.3.0 (clang-703.0.29),编译后运行,输出乱码

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/490680

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX