我正在使用' 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循环没有什么不同。
所以有人可以帮我解释为什么会发生这种错误吗?
答案 0 :(得分:4)
与while循环不同,递归可以†与调用堆栈的深度成比例地咀嚼堆栈空间。递归调用越多,使用的堆栈空间就越多。最终你的程序耗尽了堆栈空间并崩溃。
使用while循环。
†我说" can"因为tail recursion可能会被优化掉,将尾调用转换成简单的跳转并消除无限的内存使用。这是一个特例;它不适用于所有递归调用。也不能依赖它,因为C语言对编译器没有要求执行尾部调用消除。