socket.h 的 recv() 上的分段错误

发布于 2024-12-14 20:06:40 字数 1534 浏览 1 评论 0原文

在执行 .recv() 函数时,我遇到了一个奇怪的分段错误。这是我的代码中使用的函数recv()。

void* recv_and_update(void* t) 
{
    int tid = (int) t;
    int sockfd;
    struct sockaddr_in addr;
    int numbytes;
    char buf[BUFLEN];
    int flag = 1, len = sizeof(int);

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        printf("Failed to create socket on thread %d.\n", tid);
        exit(-1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons( node.port );
    addr.sin_addr.s_addr = htonl( INADDR_ANY );

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);

    printf("start binding.\n");

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)))
    {
        printf("Failed to bind socket on thread %d.\n", tid);
        exit(-1);
    }

    printf("binding finished.\n");

    while (1) 
    {
        printf("start recv()\n");

        if ((numbytes = recv(sockfd, buf, BUFLEN, 0)) < 0)
        {
            printf("Failed to receive msgs on thread %d.\n",
                    tid);
            exit(-1);
        }

        printf("end recv(), numbytes=%d\n", numbytes);
        buf[numbytes] = '\0';
        pthread_mutex_lock(&mutex);
        translate_and_update(buf);
        pthread_mutex_unlock(&mutex);
    }

    close(sockfd);
    pthread_exit(NULL);
}

这个问题最奇怪的部分是分段错误并不是每次都会发生。通常在接收 100 或 200 次之后(或偶尔更少的次数)。当发生这种情况时,程序只会输出我的“start recv()”句子,而不会输出“end recv()”。

所以我认为问题就发生在recv()函数中,但我没能弄清楚为什么以及如何解决这个问题。

I got a strange segmentation fault when executing recv() function of . Here's the function used recv() in my code.

void* recv_and_update(void* t) 
{
    int tid = (int) t;
    int sockfd;
    struct sockaddr_in addr;
    int numbytes;
    char buf[BUFLEN];
    int flag = 1, len = sizeof(int);

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        printf("Failed to create socket on thread %d.\n", tid);
        exit(-1);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons( node.port );
    addr.sin_addr.s_addr = htonl( INADDR_ANY );

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, len);

    printf("start binding.\n");

    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)))
    {
        printf("Failed to bind socket on thread %d.\n", tid);
        exit(-1);
    }

    printf("binding finished.\n");

    while (1) 
    {
        printf("start recv()\n");

        if ((numbytes = recv(sockfd, buf, BUFLEN, 0)) < 0)
        {
            printf("Failed to receive msgs on thread %d.\n",
                    tid);
            exit(-1);
        }

        printf("end recv(), numbytes=%d\n", numbytes);
        buf[numbytes] = '\0';
        pthread_mutex_lock(&mutex);
        translate_and_update(buf);
        pthread_mutex_unlock(&mutex);
    }

    close(sockfd);
    pthread_exit(NULL);
}

The most weird part of this problem is that the segmentation fault doesn't happen every time. Usually after 100 or 200 times of receiving ( or less times occasionally ). And when it happens, the program would only output my "start recv()" sentence without "end recv()".

So I think the problem happens right in the recv() function, but I failed to figure out why and how to fix this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花之痕靓丽 2024-12-21 20:06:40

从您的描述来看, recv() 正在阻塞,并且应用程序由于不同位置的错误而崩溃,会说在不同的线程中。

然而,buf 被声明为太小了一个字节。

如果读取了 BUFLEN 字节,numbytes 将是 BUFLEN 并且以下调用将写入分配的内存buf

buf[numbytes] = '\0';

将此更改修复

char buf[BUFLEN];

char buf[BUFLEN + 1];

From your discription it looks like recv() is blocking and the app crashes due to an error at a different location, will say in a different thread.

Nevertheless buf is declared one byte too small.

If having read BUFLEN bytes numbytes will be BUFLEN and the following call will write to memory not being allocated to be buf:

buf[numbytes] = '\0';

To fix this change

char buf[BUFLEN];

to be

char buf[BUFLEN + 1];
握住你手 2024-12-21 20:06:40

SIGSEGV 可能发生在其他地方,例如在 translate_and_update 中。

为什么不启用核心转储(例如 ulimit -c bash 内置)并使用 gdb yourprog core 调试事后核心?

The SIGSEGV could happen elsewhere, e.g. in translate_and_update.

Why don't you enable core dumps (with e.g. ulimit -c bash builtin) and debug the post-mortem core with gdb yourprog core ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文