这段代码为什么在 win 和 Linux 下结果不一样 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zynlp
V2EX    C

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

  •  
  •   zynlp 2018-09-19 09:24:40 +08:00 5431 次点击
    这是一个创建于 2633 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • win 下 vs2013 和 vs2017 结果是一样的
      a:
    • linux 下 g++ 4.8.5
      a: abc
    #include <iostream> using namespace std; struct A{ const char* a; }; void f(A* a){ string s("abc"); a->a = s.c_str(); } nt main(int argc, char* argv[]){ A a; f(&a); printf("a: %s\n", a.a); return 0; } 

    这属于 ub 的问题吗?

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

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

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

    你汇编跟踪以下,也能搞清楚为什么会那样输出,一句话,各有各的道理,编译器不背锅。
    nutting
        20
    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),编译后运行,输出乱码
    tourist2018
        21
    tourist2018  
       2018-09-19 15:15:34 +08:00
    @zivyou #6 和操作系统应该没关系 和编译器有关系 而且可以直接使用 printf 方法么?这不是 stdio.h 里面的库函数?
    wwqgtxx
        22
    wwqgtxx  
       2018-09-19 17:49:44 +08:00
    @tourist2018 有些编译器的 iostream 文件中会导入 cstdio 所以可以直接用
    neptuno
        23
    neptuno  
       2018-09-19 17:59:24 +08:00
    编译器不一样。有些未定义行为在不同编译器不一样的
    iceheart
        24
    iceheart  
       2018-09-19 23:17:02 +08:00 via Android
    这不是 ub,这是野指针
    msg7086
        25
    msg7086  
       2018-09-20 00:34:50 +08:00
    刚想说,这就是野指针啊。(然后楼上说了。)
    随便指向内存中一块不属于你的地址,出来的是啥就是啥。
    如果内核看你不爽,可以直接杀掉你的进程。如果他没那么凶,那就让你随便读点内存里的辣鸡数据。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5321 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 08:59 PVG 16:59 LAX 00:59 JFK 03:59
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86