无限递归变为D模式过程

时间:2015-02-26 13:18:17

标签: c++ linux recursion

考虑这个程序:

int w(int x, int y){
    if(x != y) {
        w(x, y);
    }else return x+y;
}

这样称呼:

w(0, 5);

对于不同的值(如上所述),它会生成无限递归。问题是,一旦程序以这种方式启动,特定进程就会变成D模式(等待内部I / O,因此无法触及)。

top see untitled1

采取正常循环

while(1){
    if(0 != 5){
        //foo
    }else{
        //bar
    }
}

生成R状态模式 - 完全能够获得SIGKILL。

enter image description here

虽然正常循环在性能方面优于递归;系统应该仍然能够杀死这个过程。

为什么会这样?以及如何远程预防?

代码将由程序执行编译,该程序通过套接字将其输出返回给webclient。因此,无法控制用户尝试编译的内容。

修改

无处不在的编译和运行代码的过程:

$ g++ main.cpp -o m
$ ./m

EDIT2:

$ g++ --version
g++ (GCC) 4.9.2 20150204 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ df --print-type
Filesystem     Type     1K-blocks      Used Available Use% Mounted on
/dev/sda2      ext4     957174124 168965980 739563400  19% /
dev            devtmpfs   4087124         0   4087124   0% /dev
run            tmpfs      4089872       528   4089344   1% /run
tmpfs          tmpfs      4089872        76   4089796   1% /dev/shm
tmpfs          tmpfs      4089872         0   4089872   0% /sys/fs/cgroup
tmpfs          tmpfs      4089872      1052   4088820   1% /tmp
tmpfs          tmpfs       817976        12    817964   1% /run/user/1000

测试是在Arch Linux x64(使用最新的gcc)上完成的。

EDIT3:

即使重新安装操作系统,也会出现同样的问题。该图像也已在另一台PC上使用,不会出现此问题。

2 个答案:

答案 0 :(得分:1)

'我不确定理解:

以这种方式启动命令:

./m & echo $! > mpid

所以杀死进程:

kill $(cat mpid)

答案 1 :(得分:1)

我将从这个答案开始引用(zerodeux):Linux Process States

  

... D状态( TASK_UNINTERRUPTIBLE )是一种特殊的睡眠模式,仅在内核空间代码路径中触发,当代码路径无法中断时(因为编程很复杂),大部分时间都在希望它很快会阻止。我相信大多数“D州”实际上是看不见的,它们的寿命非常短暂,并且无法通过“顶层”等采样工具观察到。

所以,内核可能会为一个进程设置 D状态,因为它正在调用某个函数(在它被调用的函数的正确时刻,没有别的)因为涉及内存工作,调用堆栈修改和其他复杂的事情。

您的代码几乎没有在w(x, y)次来电之间留下任何时间,因此可能会导致您看到连续D状态

我无法重现你的代码的行为,但我有一个实验,在调用w(x, y)之前设置一个时间睡眠(大约一秒就够了),看看发生了什么。

另一方面,我认为该程序实际上正在执行,实际上在您的代码中,您将xy作为值传递,因此,在每个调用中都会生成副本,并且将comsume内存(调用堆栈也消耗内存)。然后你可以(另一个实验)检查内存消耗,如果没有执行程序,内存消耗会保持不变。