c - 为什么不能为 Linux 非阻塞套接字递归调用 'select'

标签 c linux recursion

我正在使用“老式”SELECT 在 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循环没什么区别。

那么谁能帮我解释为什么会发生这个错误?

最佳答案

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

使用 while 循环。

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

关于c - 为什么不能为 Linux 非阻塞套接字递归调用 'select',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32896098/

相关文章:

c - 循环中动态 malloc - seg 错误

c - 未定义的函数在内核linux中插入新模块

c - 在哪里可以找到 eventfd_write 文档?

c++ - 如何在 Haskell 中使用我的递归函数?

c++ - C可以用来捕获机器上的系统调用吗?

c - 返回 C 中的字符指针数组

linux - 我可以用 supervisord 监控守护进程/服务吗?

c - 从第一个字符串中的第二个字符串中删除所有出现的所有字符

python - 如何列出模块所依赖的用户创建的 python 文件?

javascript - 如何在 Swift 中编写这个递归函数?