#c
#c
Вопрос:
Я пытаюсь добавить полученные данные в буфер, который необходимо настраивать во время выполнения (я считываю размер из файла или командной строки).
Итак, в основном я определяю свою buffersize
и выделяю область памяти, используя calloc
(я также добавляю общий набор для установки размера буфера, если его нет в файле конфигурации или командной строке — давайте предположим, что мы используем это сейчас).
Я добавляю только применимые строки кода.
int buffersize=10000;
void *BuffPtr = (void *)calloc(1,buffersize * sizeof(char));
Затем у меня recv
есть из UDP (я пробовал получать в массив символов и динамически выделяемый массив — оба работают нормально)
// Setup socket......
void *PktBuff = (void *)calloc(1,1000 * sizeof(char));
// Loop and receive many packets......
rcvd_bytes=recv(recv_socket, PktBuff, 1000, 0);
На данный момент я могу написать содержимое, PktBuff
и это работает нормально. Но я хочу объединить несколько полученных пакетов в моем динамически распределяемом массиве ( BuffPtr
определенном выше).
Я пробовал strcat, но я просто удаляю мусор, если пытаюсь записать первый полученный пакет, не получая другого пакета.
strcat(BuffPtr, PktBuff);
Что я делаю не так??
Заранее благодарю.
Комментарии:
1. strcat использует » в качестве завершителя строки. Попробуйте добавить его после strcat .
2. Вы выполняете
calloc
вызов неправильно: первый аргумент — это количество выделяемых элементов (buffersize
в первом фрагменте кода), а второй аргумент — размер каждого элемента. Так и должно бытьcalloc(buffersize, sizeof(char))
.3. @BigMike ошибка нет … это предполагает, что BuffPtr состоит только из байтов, отличных от 0.
Ответ №1:
Ваши данные, похоже, не являются строками с завершением 0, которые вы можете использовать memmove
вместо этого.
Комментарии:
1. Возможно, он мог бы работать с чтением в 999 байт в PktBuff? Поскольку calloc ноль инициализирует память.
2. Или выделение 1001 байта. То есть, если мы предположим, что в данных нет нулей.
3. Майкл, я попробовал memove, это работает для первого экземпляра, затем я получаю мусор для второго и последующих пакетов.
4. Просто будьте осторожны с тем, что и куда вы перемещаете, и убедитесь, что у вас достаточно места для перемещения вещей.
5. Хорошо, у меня достаточно места, но все та же проблема — мой цикл recv объединяется в первый раз, но во второй раз в конец моего динамически выделяемого массива добавляется только одна строка «мусора» — или так кажется — буфер recv содержит правильную информацию, но memmoveили memcpy просто добавляет мусор. Какие-нибудь идеи, пожалуйста?
Ответ №2:
Несколько моментов и наблюдений:
- Не приводите возвращаемое значение
malloc()
в C. - Выражение
sizeof (char)
представляет собой многословный способ записи1
, умножение на него редко бывает информативным. - Убедитесь, что все ваши данные завершаются 0 (строки), иначе вы не сможете использовать строковые функции, поскольку это то, что им требуется.
- Вероятно, вам следует просто использовать дополнительный
size_t
счетчик для отслеживания количества байтов в BuffPtr и использовать его иmemcpy()
для добавления.
Комментарии:
1. Спасибо, у меня есть счетчик общего количества байтов в BuffPtr, и, следуя совету Майкла, я использовал memove, что немного улучшает ситуацию. Должно быть, мне не хватает чего-то вроде завершающей строки в пакете?? Будет проверяться.
Ответ №3:
Хорошо, ряд проблем в вашем коде strcat НЕ является правильным способом добавления двоичных данных. Вот полуустойчивая реализация. Я НЕ проверял его на наличие синтаксических ошибок, просто ввел его, пожалуйста, изучите его в качестве примера и адаптируйте к своему коду.
/* total number of bytes you are willing to receive in single a single receive */
#define MAX_RECV_BUFFER 1000
/* total number of bytes you are willing to store in memory */
#define MAXBYTES MAX_RECV_BUFFER*1000
int append_bytes() {
char rcvbuf[MAX_RECV_BUFFER]; /* buffer where things are received */
void *buf = NULL; /* buffer where bytes are collected */
size_t rcvlen; /* length of data received */
size_t buflen = 0; /* total bytes */
while(1) {
void *p;
rcvlen = recv(recv_socket, rcvbuf, MAX_RECV_BUFFER, 0);
if ( rcvlen < 0 ) { manage_error(); }
if ( rcvlen == 0 )
break;
if ( buflen rcvlen > MAXBYTES)
break;
p = realloc(buf, buflen recvlen);
if ( !p ) { manage_memory_error(); }
buf = p; /* we have enough space */
memcpy(buf buflen, rcvbuf, recvlen); /* append new content to end of buffer */
buflen =recvlen; /* add length to buflen */
}
}
Комментарии:
1. Спасибо, но компилятору не нравится memcpy. Я объявил вещи точно так же, как вы (удалив мой предыдущий calloc), и получаю ошибку компилятора, ссылающуюся на аргумент buf buflen в memcpy: выражение должно быть указателем на полный тип объекта??????