此代码产生分段错误:
int main(int argc, char *argv[]){
int *n;
*n = atoi(argv[1]);
printf("n: %d \n", *n);
return 0;
}
虽然这有效:
int main(int argc, char *argv[]){
int *n;
*n = atoi(argv[1]);
pid_t pid = fork();
if (pid == 0)
return 0;
else
printf("n: %d \n", *n);
return 0;
}
为什么第二个用叉子工作?我知道在int *n
之后,我应该使用int
为malloc()
分配空间,但使用fork()
似乎会自动执行此操作。
编辑: 现在我明白了未定义的行为:) 但现在我问:这个具体案例的原因是什么?
答案 0 :(得分:7)
它不起作用。 (或者更确切地说,你有未定义的行为)
1)fork只是隐藏了segfault,因为你没有检查子进程的退出代码。
2)记忆的分配不是自动的 - 永远!
您只是写一个随机位置,您可能只是“幸运”,在第二个版本中,随机位置在您的处理空间内。
答案 1 :(得分:4)
您的代码段都会调用undefined behaviour,礼貌,
*n
argv[1]
(如果argc
不是>=2
)分段错误是 UB的众多副作用之一。 UB案例也包括无缝工作场景。
为什么第二个用fork工作?
它与fork()
UB的存在(或不存在)无关。 TL; DR
但是使用fork()似乎会自动执行此操作。
视觉效果可能具有欺骗性。不要把钱花在UB上。
答案 2 :(得分:3)
因为n
未初始化并因此指向未知的内存地址,所以您正在调用未定义的行为。它可能会崩溃(如第一个示例中所示),或者可能不会崩溃(如第二个示例中所示)。
在这样的情况下,添加未使用的变量这样简单的事情会导致程序崩溃,而不是之前,反之亦然。
为n
分配内存,您将不会遇到此问题。
编辑:
当你运行第二个程序时运行./test 100
,无论多少次运行,这都是运气的问题。您添加了对fork
(在这种情况下)的调用的事实恰好重新排列了内存布局的方式,以便它可以工作。稍后您可能决定拨打printf
进行额外的调试,突然之间它再次开始崩溃。
添加fork
调用并未自动分配任何空间。
防止崩溃的唯一方法是为n
分配内存,并确保argc
至少为2,以便argv[1]
指向某个有意义的内容。
答案 3 :(得分:0)
当你运行fork并且返回0时,你没有看到segfault,你的代码永远不会运行printf ("% d", *n)
当您尝试访问不允许的内存位置时会发生分段错误,因此解决方案是通过malloc或calloc函数分配内存,否则仍会出现问题。 试试这个:
n=malloc(sizeof(int));
*n=atoi(argv[1]);
问候