Ошибка сегментации на recv () сокета.h

#c #sockets #udp #segmentation-fault #recv

#c #сокеты #udp #ошибка сегментации #recv

Вопрос:

Я получил странную ошибку сегментации при выполнении функции 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(amp;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, amp;flag, len);

    printf("start binding.n");

    if (bind(sockfd, (struct sockaddr*)amp;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=%dn", numbytes);
        buf[numbytes] = '';
        pthread_mutex_lock(amp;mutex);
        translate_and_update(buf);
        pthread_mutex_unlock(amp;mutex);
    }

    close(sockfd);
    pthread_exit(NULL);
}
  

Самая странная часть этой проблемы заключается в том, что ошибка сегментации возникает не каждый раз. Обычно после 100 или 200 раз приема (или иногда меньше раз). И когда это произойдет, программа будет выводить только мое предложение «start recv()» без «end recv()».

Итак, я думаю, что проблема возникает прямо в функции recv (), но я не смог выяснить, почему и как это исправить.

Комментарии:

1. Также может произойти сбой в другом потоке во время recv() ожидания данных. Но это всего лишь еще одно предположение. Если вы хотите точно знать, запустите это в отладчике.

2. Каждый раз, когда происходит эта ошибка, выводится start recv() без end recv() . Так не должно быть, если ошибка произошла в другом потоке. (О, я забыл упомянуть, что этот поток является единственным принимающим потоком в моей программе.)

Ответ №1:

Из вашего описания похоже, что recv() происходит блокировка, и приложение выходит из строя из-за ошибки в другом месте, скажем, в другом потоке.

Тем не менее buf объявлено, что один байт слишком мал.

Если прочитанные BUFLEN байты numbytes будут BUFLEN , и следующий вызов запишет в память, не выделяемую для быть buf :

 buf[numbytes] = '';
  

Чтобы исправить это изменение

 char buf[BUFLEN];
  

быть

 char buf[BUFLEN   1];
  

Комментарии:

1. Я пытался написать, recv(sockfd, buf, BUFLEN - 1, 0) что может привести к тому же эффекту, что и ваша модификация. Однако это тоже не сработало.

2. lastland: Тогда должна быть другая ошибка! Возможно, вы захотите показать нам, что translate_and_update() делает

3. Поскольку каждый раз, когда возникает эта ошибка, вывод start recv() без end recv() , я думаю, что ошибка возникает именно в части функции recv (), если я что-то не пропустил или неправильно понял.

4. @lastland: Хорошо, из этого факта я бы сделал вывод, recv() что это блокировка, и приложение вылетает из-за ошибки в другом месте, скажем, в другом потоке.

5. О, возможно, вы правы, и я действительно могу пропустить что-то глупое. Теперь я пытаюсь следовать этому примеру и выяснить, что именно происходит. Спасибо.

Ответ №2:

SIGSEGV может произойти в другом месте, например в translate_and_update .

Почему вы не включаете дампы ядра (например, с помощью ulimit -c встроенного bash) и не отлаживаете посмертное ядро с помощью gdb yourprog core ?