我正在使用“老式”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/