考虑这个简单的代码片段:
{
if(fork())
{
printf("Parent terminated\n");
}
else
{
char *s = "hello world";
*s = 'H';
printf("child terminated\n");
}
wait(NULL);
return 0;
}
当我编译它时,我没有像分配给* s那样得到分段错误错误 输出是: 父终止(没有打印子终止)
现在如果我删除两行char * s = ......' H'我得到了正常的输出。
有人可以解释一下
答案 0 :(得分:3)
首先,您无需为了触发未定义的行为(例如修改字符串文字)而获得分段错误或任何已定义的行为。虽然在Linux上,字符串文字被放入只读内存中,因此在Linux上修改它们通常会导致分段错误。
那么为什么这段代码不能触发段错误呢?它确实如此,但你只是看不到它,因为你分叉了。
当您通过调用wait
检测到它生成的进程以SIGSEGV
终止时,您的shell(例如bash)会打印“Segmentation Fault(core dumped)”消息(例如bash)( segfault)信号。但是,您的shell不会收到有关子进程退出的任何通知;你的父进程会。
您的父进程调用wait
等待,并在终止时获取退出代码。如果您没有通过传递NULL
等待忽略退出代码,则可能会看到退出代码为-11
或-SIGSEGV
。
所以它是segfaulting;你的父进程只是忽略了孩子的分段通知。
答案 1 :(得分:1)
首先,其他人所说的是正确的:行为是未定义的,在执行此操作时,您不能特别依赖任何行为。
但是,我怀疑发生的事情是孩子实际上 有分段错误。但是,您在终端中看到的熟悉的“Segmentation fault”消息实际上是由您的shell在您运行seg故障时打印的。
但是,因为这是你运行的东西的孩子,你的shell没有注意到。如果您已配置核心转储(例如ulimit -c unlimited
),我希望您能从seg故障子进程中找到核心文件。