V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zynlp
V2EX  ›  C

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

  •  
  •   zynlp · 2018-09-19 09:24:40 +08:00 · 5003 次点击
    这是一个创建于 2294 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 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();
    }
    
    int 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   ·   实用小工具   ·   987 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:27 · PVG 05:27 · LAX 13:27 · JFK 16:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.