免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3794 | 回复: 5
打印 上一主题 下一主题

多线程编程出现Segmentation fault,请高手帮忙分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-08 14:34 |只看该作者 |倒序浏览
pid  3287] write(1252, "<html><head>\n\n  \n    \n    \n    \n"..., 131072 <unfinished ...>
[pid  3286] <... epoll_wait resumed> {{EPOLLIN, {u32=186946376, u64=17117145668555592}}}, 40000, -1) = 1
[pid  3286] epoll_wait(11,  <unfinished ...>
[pid  3287] <... write resumed> )       = 13140
[pid  3287] write(1252, "llCatPopoverDiv_OuterX\"><span id"..., 117932) = -1 EAGAIN (Resource temporarily unavailable)
[pid  3287] select(1253, NULL, [1024 1025 1154 1155 1156 1157 1160 1164 1165 1167 1168 1169 1170 1171 1173 1174 1175 1177 1178 1180 1181 1183 1187 1196 1197 1200 1201 1202 1203 1205 1213 1215 1219 1223 1224 1226 1229 1231 1232 1235 1236 1237 1238 1241 1243 1251 1252], NULL, {3, 0}) = 46 (out [1024 1025 1154 1155 1156 1157 1160 1164 1165 1167 1168 1169 1170 1171 1173 1174 1175 1177 1178 1180 1181 1183 1187 1196 1197 1200 1201 1202 1203 1205 1213 1215 1219 1223 1224 1226 1229 1231 1232 1235 1236 1237 1238 1241 1243 1251], left {3, 0})
[pid  3287] --- SIGSEGV (Segmentation fault) @ 0 (0) ---

反复看过代码,select之后是printf函数,不可能出现段错误.而且并不是程序一运行到这边就出错.是运行一段时间后出现(几分钟不等).

还有一个疑问是,select的maxfd是否可以大于1024, select之前我已经FD_ZERO(&fdSet);  FD_SET(1252, &fdSet);为什么select的系统调用打印出那么多FD出来呀: [1024 1025 1154 1155 1156 1157 1160 ....  注意,FD_SET我只加了1252

论坛徽章:
0
2 [报告]
发表于 2008-11-08 14:39 |只看该作者
maxfd 应该是1024,有限制的。

论坛徽章:
0
3 [报告]
发表于 2008-11-08 15:04 |只看该作者
原帖由 eveson 于 2008-11-8 14:39 发表
maxfd 应该是1024,有限制的。


FD_SETSIZE, 好象是select一次可处理的fd数量吧.我现在select只侦听一个FD,只是这个FD的值大于1024而已

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
4 [报告]
发表于 2008-11-08 15:23 |只看该作者

回复 #3 mackon_jong 的帖子

FD_SET一般是整数数组,用bit对应FD,FD_SETSIZE确实就是限定最大的FD而不是总的处理FD数,这也是select不同于poll/epoll的一个限制

论坛徽章:
0
5 [报告]
发表于 2008-11-08 16:10 |只看该作者
改成epoll还是出错
[pid  3340] epoll_create(65535)         = 1230
[pid  3340] epoll_ctl(1230, EPOLL_CTL_ADD, 1252, {EPOLLOUT, {u32=165158888, u64=15763973250490344}}) = 0
[pid  3340] epoll_wait(1230, {{EPOLLOUT, {u32=165158888, u64=15763973250490344}}}, 1, 3) = 1
[pid  3340] close(1230)                 = 0
[pid  3340] write(1, "yhl test before checkout(3) <--B"..., 92yhl test before checkout(3) <--BaseSocket.cpp:437yhl test epoll_wait=1 <--BaseSocket.cpp:77
) = 92
[pid  3340] write(1, "yhl test selectEINTR1=1\n", 24yhl test selectEINTR1=1
) = 24
[pid  3340] --- SIGSEGV (Segmentation fault) @ 0 (0) ---

我把我的函数调用贴上来.按程序流程, [pid  3340] write(1, "yhl test selectEINTR1=1\n", 24yhl test selectEINTR1=1后,应该是printf("yhl test after checkout(%d)=%d <--%s:%d",  timeout, ret, __FILE__, __LINE__), 但却出现段错误了,会不会别的线程访问指针越界,修改了我这个线程的堆栈数据.

int selectEINTR1(int fd, int event, int timeout)
{
    int epfd;
    struct epoll_event ev;
    struct epoll_event events[1];
    int rc;

    ev.events = event;//ev.events = event | EPOLLET | EPOLLONESHOT;

    epfd = epoll_create (65535);
    if (epfd == -1){
        printf("create epoll fail<--%s:%d\n", __FILE__, __LINE__);
        return 0;
    }

    if (epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &ev) != 0){
        if (epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &ev) != 0){
            printf("epoll_ctl fail<--%s:%d\n", __FILE__, __LINE__);
            return 0;
        }
    }

    rc = epoll_wait (epfd, events, 1, timeout*1000);
    close(epfd);
    printf("yhl test epoll_wait=%d <--%s:%d\n", rc, __FILE__, __LINE__);

    return rc;
}

int BaseSocket::readyForOutput(int timeout)
{
    int ret = 0;

    //ret = selectEINTR(sck + 1, NULL, &fdSet, NULL, &t);
    ret = selectEINTR1(sck, EPOLLOUT, timeout);
    printf("yhl test selectEINTR1=%d\n <--%s:%d", ret, __FILE__, __LINE__);

    return ret;
}
bool BaseSocket::writeToSocket(char *buff, int len, int timeout, bool check_first) throw(exception)
{
    int actuallysent = 0;
    int sent;
    bool firstflag = true;
    int errcount = 0;
    int ret = 0;

    while (actuallysent < len) {
        sent = write(sck, buff + actuallysent, len - actuallysent);
        if (sent < 0) {
            if (errno == EAGAIN && errcount < 3){
                printf("yhl test before checkout(%d) <--%s:%d",  timeout,  __FILE__, __LINE__);
                ret = readyForOutput(timeout);
                printf("yhl test after checkout(%d)=%d <--%s:%d",  timeout, ret, __FILE__, __LINE__);
                if (ret < 0)
                    return false;
                else if (ret == 0)
                    errcount++;
                else
                    errcount = 0;

                continue;
            }
            return false;
        }
        else if (sent == 0) {
            errcount = 0;
            return false;  // other end is closed
        }

        actuallysent += sent;
    }

    //do_log(LOG_DEBUG, "yhl test send actuallysent:%d <--%s:%d", actuallysent, __FILE__, __LINE__);
    return true;
}

[ 本帖最后由 mackon_jong 于 2008-11-8 16:12 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-11-08 17:41 |只看该作者
没看出来~~

[ 本帖最后由 Roemer 于 2008-11-8 18:02 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP