Сбой malloc / calloc в стороннем потоке в Linux - PullRequest
0 голосов
/ 24 мая 2011

Я пишу сервер-клиентское приложение на C и делюсь информацией. Сервер работает в двухпотоковом режиме - основной поток ожидает ввода, а побочный поток отвечает на запросы клиентов. Клиент работает так же, но он ожидает ввода данных от пользователя (из стандартного ввода) и, если он получает правильную команду, отправляет запрос на сервер и ожидает ответа. Ожидание выполняется в стороннем потоке обработки ответов. Хотя это выглядит нормально и работает в дистрибутиве на основе Ubuntu (я использую Ultimate Edition 2.7), он падает на каком-то другом дистрибутиве. Вот что происходит.

Сервер работает без нареканий, но клиент страдает от glibc обнаруженных сбоев (надеюсь, я правильно набрал). Получив ответ, он анализирует свою структуру, которая содержит:
а) заголовок,
б) некоторые статические идентификаторы,
c) раздел данных, содержащий длину и сами данные.

Что происходит:
а) клиент получает пакет,
б) клиент проверяет его размер (не менее sizeof(header) + sizeof(static_data) + sizeof(length) + data - и размер данных такой же большой, как говорит длина)),
в) создает структуру - преобразование из буфера символов в структуры выше, d) создает некоторые другие структуры, хранящие эти структуры.

Структура интерпретируется правильно. Я проверил это, отправив «фиксированную» структуру клиенту через интерфейс сервера и распечатав оригинал, отправленные данные и полученную информацию. Так что это не тот случай. Все хорошо, чтобы указать в).

К пункту d) Я работаю над буфером, используемым для приема входящих пакетов (указан максимальный размер и буфер этого размера). Для хранения структур я попал в данные. Я делаю это:
а) выделение новой памяти правильного размера
б) копирование данных.

Я не должен обсуждать метод. Все в порядке, пока работает . Но, как я уже сказал, это не касается другого дистрибутива. Сбой при выделении памяти MALLOC в пункте а). И это терпит неудачу на всем. Я предположил, что это может быть проблема с поточной безопасностью malloc и / или printf в другом дистрибутиве, но проблема в том, что основной поток МОЖЕТ простаивать в методе scanf (..).
Вернуться к теме: ничего не получается:
char* buffer = (char*)malloc(fixed_size * sizeof(char))
STRUCT_T* struct = (STRUCT_T*)malloc(sizeof(STRUCT_T)) и так далее. Независимо от того, что я пытаюсь выделить, он всегда выдает ошибку, обнаруженную glibc, и всегда указывает на метод malloc (даже если это calloc).

Это заставляет меня задуматься, что с этим не так? И это мой вопрос темы. Похоже, я переполняю «пространство памяти», но я сомневаюсь в этом, поскольку это всегда происходит при первом получении ответа. Я был бы признателен за любую помощь и может опубликовать более подробную информацию, если это необходимо. Боковые резьбы соединяются.

Опции, с которыми я компилирую:
CC = gcc CFLAGS = -Wall -ansi --pedantic -c -O0 -g -std=c99 -pthread $(CC) $(CFLAGS) server.c -o server.o gcc server.o $(OBJECTS) -o server -pthread -lm
и включает в файл client.c:
sys/fcntl.h netdb.h errno.h stdio.h unistd.h stdlib.h string.h time.h pthread.h math.h

Я не новичок в C и Linux, но я в основном работаю на Windows и C ++, так что это довольно тревожно. И, как я уже сказал, он отлично работает на используемом мной дистрибутиве, но не на каком-то другом, когда буфер анализируется правильно.


Заранее спасибо.

1 Ответ

2 голосов
/ 24 мая 2011

Когда происходит сбой malloc, обычно это происходит потому, что вы уже наступили на данные, которые он использует для управления собой (и бесплатно). Диагностировать в момент аварии сложно или невозможно, потому что проблема действительно произошла в какое-то время раньше. Как уже было предложено, лучший способ выяснить, где произошла предыдущая перезапись памяти, - это запустить вашу программу через такие программы, как valgrind, cleany, insure ++ и т. Д. Она сообщит вам, если вы перезаписали что-то, чего не должны делать. valgrind - бесплатное программное обеспечение, и оно, вероятно, уже установлено. Это может быть так же просто, как прикрепить слово valgrind перед всем остальным в строке вызова вашего клиента.

...