【问题标题】:About the socket select() crash关于套接字 select() 崩溃
【发布时间】:2015-07-07 02:18:22
【问题描述】:

旧版本

FD_ZERO(&rfds);
FD_ZERO(&master);
FD_SET(sockserver, &master);
fdmax =  sockserver;

for(;;) {
    rfds = master;
    if( select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
        perror("select");
        exit(1);
    }

新版本

FD_ZERO(&rfds);
FD_ZERO(&master);
FD_SET(sockserver, &master);
fdmax =  sockserver;

for(;;) {
    FD_ZERO(&rfds);
    for(j=0;j<max_socket;j++){
        if(FD_ISSET(j,&master))
            FD_SET(j,&rfds);
    }
    /* Not copying directly, because you can't assume that the set is integer type.
         It may be anything. */
    if( select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
        perror("select");
        exit(1);
    }

我尝试了旧版本,运行到select()时会崩溃,然后我搜索新版本并尝试,它仍然崩溃。我还尝试移出所有我认为可能是堆栈溢出的局部变量,但它仍然崩溃。

有人可以回答这个问题吗? 非常感谢。

【问题讨论】:

  • max_socket 设置为什么?为什么不是fdmax + 1
  • 这是一个长镜头,但请检查 sockserver 是否小于 FD_SETSIZE。
  • 另外,至少在 BSD 上,有 void FD_COPY(fd_set *fdset_orig, fd_set *fdset_copy); — 使用 cack-handed '(src, dst)' 参数而不是像大多数其他复制函数一样的 '(dst, src)' (@987654330 @、memmove() 等)。不幸的是,POSIX 没有对其进行标准化(参见FD_CLR());我想知道这是否是因为不同的实现。 Linux(已检查 Ubuntu 14.04 LTS)似乎没有 FD_COPY
  • 您可能还注意到 POSIX &lt;sys/select.h&gt; 说:&lt;sys/select.h&gt; 标头应将 fd_set 类型定义为结构。 至少有中等机会可以使用结构副本,除非您正在修改它的大小 - 请参阅 Are there any platforms where using structure copy on an fd_set causes problems? 和我的 answer 那里。 (也许 5 年后需要更新?)
  • 关于这一行:'rfds = master;'这两个项目都是包含多个字段的结构。所以一个简单的任务是行不通的。建议使用 memcpy(&rfds, &master, sizeof( rfds ) );

标签: c sockets embedded-linux


【解决方案1】:

在这两个版本上,您都没有正确设置fdmax。如果master 中的任何套接字大于sockserver 的值,select() 将忽略它们。 select()的第一个参数必须比rfds中的最大socket高+1。

此外,在 版本中,不能保证rfds = master 是有效操作。在可能出错的平台上,请改用FD_COPY()

FD_COPY(&master, &rfds); 

但在这种情况下,通过使用版本,您不需要使用FD_COPY()(如果可用)。

正如 Craig 在 cmets 中所说,确保 max_socket 确实有效,不超过 FD_SETSIZE 等。

试试这个:

FD_ZERO(&master);
FD_SET(sockserver, &master);
...    

FD_ZERO(&rfds);
fdmax = -1;
for(j = 0; (j < max_socket) && (j < FD_SETSIZE); ++j){
    if (FD_ISSET(j, &master)) {
        FD_SET(j, &rfds);
        fdmax = j;
    }
}
if (select(fdmax+1, &rfds, NULL, NULL, NULL) == -1) {
    perror("select");
    exit(1);
}
...

如果您仍然遇到问题,那么您需要提供更真实的MCVE 来演示实际存在的问题。

【讨论】:

    猜你喜欢
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2013-06-14
    • 2021-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多