#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
?