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

C 语言新手请教一个段错误问题

  •  
  •   Uu6p94cFbGXx7duC · 2021-04-29 17:35:09 +08:00 · 2477 次点击
    这是一个创建于 1065 天前的主题,其中的信息可能已经有所发展或是发生改变。
    #include <stdio.h>
    #include <stdlib.h>
    
    struct Child {
    };
    
    struct Parent {
        struct Child *child;
    };
    
    int main(void)
    {
        struct Child *child = (struct Child *)malloc(sizeof(struct Child));
        struct Parent *parent;
    
        parent->child = child;
    
        return 0;
    }
    

    报错为:bash: line 1: 30009 Segmentation fault: 11 "~/Code/hello_c/main",但是如果把这两行交换,就不会报错,如下:

        struct Parent *parent;
        struct Child *child = (struct Child *)malloc(sizeof(struct Child));
    

    想不通是为啥,特来请教。

    第 1 条附言  ·  2021-04-29 19:50:09 +08:00
    突然懂了,parent 里面的指针需要分配内存。关帖。
    21 条回复    2021-05-04 23:28:51 +08:00
    justou
        1
    justou  
       2021-04-29 17:38:39 +08:00
    你的 parent 指针没分配内存
    newmlp
        2
    newmlp  
       2021-04-29 19:28:49 +08:00   ❤️ 1
    这。。。也太新手了
    YouKnowIt
        3
    YouKnowIt  
       2021-04-30 15:51:15 +08:00
    哈哈哈,果然是新手
    araraloren
        4
    araraloren  
       2021-04-30 16:20:52 +08:00
    这。。建议学习 rust 去吧
    Uu6p94cFbGXx7duC
        5
    Uu6p94cFbGXx7duC  
    OP
       2021-04-30 16:23:09 +08:00 via iPhone   ❤️ 1
    各位,我才学了一天,大可不必冷嘲热讽。原以为 v 站风气会好一点,看来也不过如此。顺便请教一下,如何注销账号。
    rbut
        6
    rbut  
       2021-04-30 17:37:16 +08:00
    脾气好像有点大。
    lance6716
        7
    lance6716  
       2021-04-30 21:42:50 +08:00 via Android   ❤️ 1
    自己能说自己是新手,别人说不行🤔
    JamesMackerel
        8
    JamesMackerel  
       2021-05-01 12:19:19 +08:00 via iPhone
    我有点好奇,为啥交换就不会错了……
    killeder
        9
    killeder  
       2021-05-01 15:33:34 +08:00
    newbie
    sunnywqf
        10
    sunnywqf  
       2021-05-02 09:00:55 +08:00 via iPhone
    @JamesMackerel 同好奇,一会儿用 Windows 试试
    sunnywqf
        11
    sunnywqf  
       2021-05-02 09:34:26 +08:00
    @JamesMackerel #8 估计楼主说错了吧, 用 https://gcc.godbolt.org/ 看了下生成的 arm 汇编, 交换这两行,没有任何的变化 .
    sunnywqf
        12
    sunnywqf  
       2021-05-02 09:37:33 +08:00
    多执行几遍呢, 是不是会有出错的时候.
    zjsxwc
        13
    zjsxwc  
       2021-05-02 13:42:15 +08:00
    换不换顺序都会报错

    [zjsxwc@manjaro]$ git diff q.c q2.c
    diff --git a/q.c b/q2.c
    index 032ef4a..517a6db 100644
    --- a/q.c
    +++ b/q2.c
    @@ -10,8 +10,8 @@ struct Parent {

    int main(void)
    {
    - struct Child *child = (struct Child *)malloc(sizeof(struct Child));
    struct Parent *parent;
    + struct Child *child = (struct Child *)malloc(sizeof(struct Child));

    parent->child = child;

    [zjsxwc@manjaro]$ gcc -o q.out q.c
    [zjsxwc@manjaro]$ gcc -o q2.out q2.c
    [zjsxwc@manjaro]$ ./q.out
    Segmentation fault (core dumped)
    [zjsxwc@manjaro]$ ./q2.out
    Segmentation fault (core dumped)
    yolee599
        14
    yolee599  
       2021-05-03 13:26:32 +08:00
    这个行为很危险啊,函数内定义的变量 parent 没初始化的时候是不确定的,也就是说你给一个不确定的地址赋值,百分百造成内存溢出。
    csfreshman
        15
    csfreshman  
       2021-05-03 22:25:41 +08:00
    正确的写法是:
    int main(void)
    {
    struct Child *child = (struct Child *)malloc(sizeof(struct Child));
    struct Parent parent;

    parent.child = child;
    printf("hello,world");
    return 0;
    }

    交换顺序也不会正确运行,最简单的写法是声明栈变量 parent,当然也可以分配堆变量(malloc),你的写法没有分配内存,直接对一个未初始化的指针操作是未定义行为。
    BrettD
        16
    BrettD  
       2021-05-04 07:07:08 +08:00
    新手脾气还这么大,牛气上天了
    ch2
        17
    ch2  
       2021-05-04 16:11:50 +08:00
    交换后没报错只是你运气好,这种写法是完全错误的
    crazytec
        18
    crazytec  
       2021-05-04 17:08:20 +08:00 via Android
    兄弟,我觉得这种问题直接上 stackoverflow 或者在各种群里问就行了(反正 rust 有中国 tg 非官方群,c 不知道有没有)。我个人的见解是 V2EX 和知乎的定位比较类似,都是偏向生活(比如讨论一下新闻或者是自己的人生经验)而非严肃的编程话题(比如说代码哪里错了之类的)。v2ex 的主页、热门机制都是为了更多人看到一个帖子并且讨论,因此很多情况下点进帖子的人根本没想解答你的疑惑(甚至连 c 语言怎么写都不知道),单纯就是想发表一下自己的意见。在这种偏技术的帖子里,他们就只好喷一下“新手”这个词。不用太放在心上就行了🙂
    Kasumi20
        19
    Kasumi20  
       2021-05-04 18:43:24 +08:00
    struct Parent *parent;

    这个应该是为定义行为吧?有的编译器会设为 0,所以段错误
    有的是个不处理的野指针,所以可能不报错。
    raysonx
        20
    raysonx  
       2021-05-04 20:54:31 +08:00 via iPhone
    @Kasumi20 全局变量的话会被初始化为 0,非全局变量的初始值是未定义的。
    gBurnX
        21
    gBurnX  
       2021-05-04 23:28:51 +08:00
    @Uu6p94cFbGXx7duC

    1.冷嘲热讽的人在哪都有。前两天国内微软 2 把手下面的一个小屁孩,带着两个小伙伴,在某和一个 IT 细分方向新晋领域的老板吵了几天架。他们那种层次,同样有冷嘲热讽的。

    2.你问问题,有高手回复,你达到目的就好。没必要注销账号。这个论坛里还是有很多大神潜伏着,时不时他们就会发点重要心得,你注销账号,不来这个论坛了,其实是你自己的损失。

    3.另外,你可以看看那些嘲讽你的小伙伴,点开他们的资料,看看他们的提问与回复。看完后,你再想想,为这种层次的人生气,值得嘛?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2758 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 11:57 · PVG 19:57 · LAX 04:57 · JFK 07:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.