关于select的一个死循环

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
int main(int argc, char *argv[]){
    int maxfd;
    char buf[256];
    fd_set rset;
    while(1){
        FD_ZERO(&rset);
        FD_SET(STDIN_FILENO,&rset);
        select(STDIN_FILENO+1,&rset,NULL,NULL,NULL);
        if(FD_ISSET(STDIN_FILENO,&rset))
            printf("hello world!\n");    
    }
    return 0;
}

  上述代码会出现死循环的情况。

select对fd的监听等同于对fd的缓冲区的监听。当fd的缓冲区有数据可读时,select返回。当输入任意字符,比如:“abc”,则“abc”被放在标准输入的缓冲当中,此时缓冲中有数据(abc)待读,所以select返回STDIN_FILENO就绪,程序输出“hello World!”。紧接着进入下一次循环,select重新将STDIN_FILENO加入监听的描述符集,由于刚刚的“abc”并没有被读出,所以仍在缓冲中,此时STDIN_FILENO的缓冲中仍有数据等待读,所以select又返回STDIN_FILENO可读就绪,又一次输出“hello world!”。之后循环情况类似,由于缓冲的的“待读”数据始终还在,所以每次select都直接返回STDIN_FILENO就绪,每次都输出“hello world!”,这就是造成程序死循环的原因。

 

转载于:https://www.cnblogs.com/lhmily/p/3960753.html

在MySQL中,可以使用变量来记录已经访问过的节点,避免重复访问,从而防止死循环。具体实现方法如下: 首先,定义一个变量,用来记录已经访问过的节点,初始值为要递归查询的节点,例如: ``` SET @node_id = 1; ``` 然后,在递归查询语句中,使用IF语句判断当前节点是否已经被访问过,如果已经访问过,则不再访问,否则继续递归查询。例如: ``` WITH RECURSIVE cte AS ( SELECT id, parent_id, name FROM my_table WHERE id = @node_id UNION ALL SELECT t.id, t.parent_id, t.name FROM my_table t JOIN cte ON t.parent_id = cte.id WHERE cte.id <> t.id AND @node_id <> t.id ) SELECT * FROM cte; ``` 在上面的查询语句中,使用了@node_id变量来记录已经访问过的节点,同时在第二个SELECT语句中加入了筛选条件@node_id <> t.id,避免重复访问。 需要注意的是,如果递归查询中存在环路,即一个节点的父节点又是它的子节点,那么上面的方法可能会进入死循环。为了避免这种情况,可以在查询语句中加入深度限制,例如: ``` WITH RECURSIVE cte AS ( SELECT id, parent_id, name, 1 AS depth FROM my_table WHERE id = @node_id UNION ALL SELECT t.id, t.parent_id, t.name, cte.depth + 1 FROM my_table t JOIN cte ON t.parent_id = cte.id WHERE cte.id <> t.id AND @node_id <> t.id AND cte.depth < 100 ) SELECT * FROM cte; ``` 上面的查询语句中,加入了深度限制,即最多递归查询100层,避免死循环
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值