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

2021-04-29 17:35:09 +08:00
 Uu6p94cFbGXx7duC
#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));

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

2639 次点击
所在节点    C
21 条回复
justou
2021-04-29 17:38:39 +08:00
你的 parent 指针没分配内存
newmlp
2021-04-29 19:28:49 +08:00
这。。。也太新手了
YouKnowIt
2021-04-30 15:51:15 +08:00
哈哈哈,果然是新手
araraloren
2021-04-30 16:20:52 +08:00
这。。建议学习 rust 去吧
Uu6p94cFbGXx7duC
2021-04-30 16:23:09 +08:00
各位,我才学了一天,大可不必冷嘲热讽。原以为 v 站风气会好一点,看来也不过如此。顺便请教一下,如何注销账号。
rbut
2021-04-30 17:37:16 +08:00
脾气好像有点大。
lance6716
2021-04-30 21:42:50 +08:00
自己能说自己是新手,别人说不行🤔
JamesMackerel
2021-05-01 12:19:19 +08:00
我有点好奇,为啥交换就不会错了……
killeder
2021-05-01 15:33:34 +08:00
newbie
sunnywqf
2021-05-02 09:00:55 +08:00
@JamesMackerel 同好奇,一会儿用 Windows 试试
sunnywqf
2021-05-02 09:34:26 +08:00
@JamesMackerel #8 估计楼主说错了吧, 用 https://gcc.godbolt.org/ 看了下生成的 arm 汇编, 交换这两行,没有任何的变化 .
sunnywqf
2021-05-02 09:37:33 +08:00
多执行几遍呢, 是不是会有出错的时候.
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
2021-05-03 13:26:32 +08:00
这个行为很危险啊,函数内定义的变量 parent 没初始化的时候是不确定的,也就是说你给一个不确定的地址赋值,百分百造成内存溢出。
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
2021-05-04 07:07:08 +08:00
新手脾气还这么大,牛气上天了
ch2
2021-05-04 16:11:50 +08:00
交换后没报错只是你运气好,这种写法是完全错误的
crazytec
2021-05-04 17:08:20 +08:00
兄弟,我觉得这种问题直接上 stackoverflow 或者在各种群里问就行了(反正 rust 有中国 tg 非官方群,c 不知道有没有)。我个人的见解是 V2EX 和知乎的定位比较类似,都是偏向生活(比如讨论一下新闻或者是自己的人生经验)而非严肃的编程话题(比如说代码哪里错了之类的)。v2ex 的主页、热门机制都是为了更多人看到一个帖子并且讨论,因此很多情况下点进帖子的人根本没想解答你的疑惑(甚至连 c 语言怎么写都不知道),单纯就是想发表一下自己的意见。在这种偏技术的帖子里,他们就只好喷一下“新手”这个词。不用太放在心上就行了🙂
Kasumi20
2021-05-04 18:43:24 +08:00
struct Parent *parent;

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

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

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

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

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

© 2021 V2EX