为什么不能打电话选择'递归地用于Linux非阻塞套接字

时间:2015-10-01 20:14:50

标签: c linux recursion

我正在使用' old-school'在Linux上实现一个非阻塞的UDP套接字。选择。基本上,我有一个运行以下函数的线程:

int NBRecv(void* pv, size_t len){
    int res = -1;
    FD_ZERO(&select_socks);    
    FD_SET(sock, &select_socks);
    int readsocks = select(sock + 1, &select_socks, (fd_set *)0, (fd_set *)0, &select_timeout);
    assert(readsocks >= 0);
    if(readsocks == 0)
        return NBRecv(pv, len);
    else {
        if(FD_ISSET(sock, &select_socks)){
            res = read(sock, pv, len);
        }
        else
            res = 0;
        return res;
    }
}

在那里你看到我再次调用该函数,如果没有可用于读取的套接字继续等待(我知道这是一个无限循环)。但是,每次运行此函数时都会出现分段错误(特别是在运行递归调用时)。删除递归调用后,一切正常。

我天真的理解是这里的递归与while循环没有什么不同。

所以有人可以帮我解释为什么会发生这种错误吗?

1 个答案:

答案 0 :(得分:4)

与while循环不同,递归可以与调用堆栈的深度成比例地咀嚼堆栈空间。递归调用越多,使用的堆栈空间就越多。最终你的程序耗尽了堆栈空间并崩溃。

使用while循环。

我说" can"因为tail recursion可能会被优化掉,将尾调用转换成简单的跳转并消除无限的内存使用。这是一个特例;它不适用于所有递归调用。也不能依赖它,因为C语言对编译器没有要求执行尾部调用消除。