Вот код не вызывающий ошибку сегментирования:
https://docs.google.com/leaf?id=0B9wfqavDettQYTJiZGRhOWUtOWE0NS00ZmI1LTk4YTAtMjMxMzA5NTExZjNj&hl=ru
А вот этот же код с минимальными изменениями почему-то вызывает:
https://docs.google.com/leaf?id=0B9wfqavDettQNTgyYzIyNjctYzZmZi00Y2ZlLWI3NDUtNDBlOGM4ZDk5OWQ1&hl=ru
( переставлены местами
char *buffer, *str;
и
int counter = 0;
)
В чем дело?
Ошибка сегментирования возникает, когда программа обращается к памяти,
которая ей не принадлежит.
> Вот код не вызывающий ошибку сегментирования:
> https://docs.google.com/leaf?id=0B9wfqavDettQYTJiZGRhOWUtOWE0NS00ZmI1LTk4YTAtMjMxMzA5NTExZjNj&hl=ru
Это тебе повезло (он должен вызывать такую ошибку). У тебя переменная
buffer не инициализируется перед передачей в sprintf(). Поэтому в момент
вызова sprintf() этот указатель указывает на какую-то случайную область
памяти. Переменную надо либо переобъявить так:
char buffer[много];
либо инициализировать путем присвоения ей того, что вернет malloc() и не
забывать в конце эту память освобождать с помощью free(). И чтобы буфер
не переполнялся, использовать snprintf.
Такие ошибки (неинициализированная переменная, выход за границу буфера)
хорошо отлавливает valgrind.
gcc -Wall --pedantic -g3 main.c
valgrind --leak-check=full --show-reachable=yes ./a.out
--
Александр Патраков
Несмотря на все while(1), при отключении клиента сервер завершает свою
работу.
То есть интересует вопрос последовательной обработки многих клиентов,
вместо одного.
Надо понять, что вообще происходит (сигнал? крах?). Для этого можно
запустить сервер под strace.
--
Александр Патраков
--
Segmentation fault
P.S. проверь, не утекают ли у тебя файловые дескрипторы. По хорошему,
если recv() вернул 0 или -1 с "невменяемой" ошибкой (т.е. не EAGAIN и не
EINTR), надо вызвать close().
--
Александр Патраков
Обычно в таких if проверяют == -1, но если на 0 реакция та же, то
можно if ( ... <= 0)
Кстати, если клиент КОРРЕКТНО отключился (TCP FIN), то:
recv может после этого получить часть данных которые клиент успел
послать,
последующие recv вернут 0.
Если продолжать делать recv() то код возврата не предсказуем (0 или
-1)
send же тоже может послать часть данных, а последующий send вернёт
(ECONNRESET или EPIPE)
Если разрыв соединения произошёл внезапно (TCP RST) (например, клиент
сам не закрыл дескриптор, в клиенте произошла ошибка, процесс был убит
и т.д.) то
recv может после этого получить часть данных которые клиент успел
послать,
последующие recv вернут -1 (ECONNRESET, EPIPE, ECONNABORTED)
send() Тоже может вернуть часть данных, после чего вернёт (ECONNRESET,
EPIPE, ECONNABORTED)
EPIPE может вернуться если соединение с 127.0.0.1 -> на 127.0.0.1 и
произошёл разрыв.
В итоге. Чтобы написать нормальную прогрмму надо проверять все виды
ошибок после каждого recv() и send(). Плюс помнить, что recv() может
вернуть 0. считать это ошибкой или нет - в зваисимости от контекста.
send() никогда не может вернуть 0.