不确定C行为;“叉形炸弹”;

不确定C行为;“叉形炸弹”;,c,fork,kill,C,Fork,Kill,所以,我创造了一个“叉子”炸弹。然而,当我在我的电脑上运行它时,它会杀死我电脑上的所有东西,进入黑屏,然后自动恢复 在我朋友的电脑上,当运行相同的精确代码时,他实际上做了一个叉炸弹,但从来没有进入杀死循环 有什么原因吗 #include <unistd.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> int main(){ int pc = 0; int*

所以,我创造了一个“叉子”炸弹。然而,当我在我的电脑上运行它时,它会杀死我电脑上的所有东西,进入黑屏,然后自动恢复

在我朋友的电脑上,当运行相同的精确代码时,他实际上做了一个叉炸弹,但从来没有进入杀死循环

有什么原因吗

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
int main(){

    int pc = 0;
    int* pids = calloc(1025,sizeof(int));
    L1:
        while(1){
            int pid = fork();
            if(pid != 0)
            {
                pc++;
                pids[pc] = pid;

            }

            if(pc == 1024)
            {
                goto L2;
                break;
            }
        }
    L2:
        while(1){
            if(pids[pc] != 0) {
                kill(pids[pc],SIGKILL);
            }

            if(pc == 0)
            {
                goto L1;
                break;
            }

            pc--;
        }
    free(pids);
}
#包括
#包括
#包括
#包括
int main(){
int-pc=0;
int*pids=calloc(1025,sizeof(int));
L1:
而(1){
int-pid=fork();
如果(pid!=0)
{
pc++;
pid[pc]=pid;
}
如果(pc==1024)
{
转到L2;
打破
}
}
L2:
而(1){
如果(PID[pc]!=0){
kill(pids[pc],SIGKILL);
}
如果(pc==0)
{
转到L1;
打破
}
个人电脑--;
}
免费(pids);
}
注意,这段代码只是为了好玩

更新:

把pc++。if语句外部导致内核死机。有人能给我解释一下原因吗

理论上,这段代码甚至不起作用。

从本质上讲,它不能有任何确定性行为。理论上,拥有无限资源的计算机可以毫无问题地继续分叉。 但实际上,我们知道计算机并没有无限的资源。因此,不同的操作系统可能以不同的方式处理资源消耗

通常,当操作系统无法生成更多进程时,内核可能会杀死“有问题”的进程,以释放资源或崩溃或进入无状态。对于内核来说,进程的指数增长通常很难处理,即使它能够识别它

所以,你不能期望任何确定性或可重复的行为。

从本质上说,不能有任何确定性行为。理论上,拥有无限资源的计算机可以毫无问题地继续分叉。 但实际上,我们知道计算机并没有无限的资源。因此,不同的操作系统可能以不同的方式处理资源消耗

通常,当操作系统无法生成更多进程时,内核可能会杀死“有问题”的进程,以释放资源或崩溃或进入无状态。对于内核来说,进程的指数增长通常很难处理,即使它能够识别它


因此,您不能期望任何确定性或可重复的行为。

您可能崩溃的原因是
fork()
可能会失败,在这种情况下,它将返回-1。当您调用
kill(-1,SIGKILL)
时,它将
SIGKILL
发送到系统上的每个进程。如果您是以特权用户的身份运行,那么这很糟糕的原因应该是显而易见的

旁注:

  • fork()
    的返回类型是
    pid\u t
    ,而不是
    int
    。在大多数情况下,
    pid\u t
    恰好适合
    int
    ,但您应该使用正确的类型

  • goto
    语句之后使用
    break
    语句是毫无意义的。无法到达
    中断

  • 如果您在编译器上启用了警告,它可能会告诉您这两种情况。


  • 您崩溃的原因可能是
    fork()
    可能会失败,在这种情况下,它将返回-1。当您调用
    kill(-1,SIGKILL)
    时,它将
    SIGKILL
    发送到系统上的每个进程。如果您是以特权用户的身份运行,那么这很糟糕的原因应该是显而易见的

    旁注:

  • fork()
    的返回类型是
    pid\u t
    ,而不是
    int
    。在大多数情况下,
    pid\u t
    恰好适合
    int
    ,但您应该使用正确的类型

  • goto
    语句之后使用
    break
    语句是毫无意义的。无法到达
    中断

  • 如果您在编译器上启用了警告,它可能会告诉您这两种情况。


  • 我的朋友和我拥有相同的电脑模型。His加载进程(跟踪top)。然而,我的只是去杀死一切我认为。我只是不明白为什么我的去死而他的不去,这是因为计算机不同,所以在某种程度上,同样的事情得到不同的处理?当你下次尝试时,即使是同一个操作系统也会有不同的行为/处理方式。当操作系统即将崩溃时,没有“预期”的行为。我的朋友和我拥有相同的计算机模型。His加载进程(跟踪top)。然而,我的只是去杀死一切我认为。我只是不明白为什么我的去死而他的不去,这是因为计算机不同,所以在某种程度上,同样的事情得到不同的处理?当你下次尝试时,即使是同一个操作系统也会有不同的行为/处理方式。当操作系统即将崩溃时,没有“预期”行为。
    ulimit-u
    是否报告相同的值?我的ulimit实际上很小,所以这可能是问题所在?@DaBler你知道如何更改Mac OS中的ulimit-u吗?我似乎找不到任何地方可以这样做。不幸的是,我不知道Mac OS。
    ulimit-u
    是否报告相同的值?我的ulimit实际上很小,所以这可能是问题所在?@DaBler你知道如何在Mac OS中更改ulimit-u吗?我似乎找不到任何关于如何做到这一点的地方。不幸的是,我不知道Mac OS。