пакеты recv с указателями - PullRequest
0 голосов
/ 22 февраля 2012

При получении входящего сообщения я получаю правильный результат, когда в структуре моего пакета есть массив фиксированного размера, например,

typedef struct inPacket{
    int cmd;
    int seqNo;
    int numbers[100];
} inPacket;

, тогда я вызываю recv вот так

char buf[1024];
recv(m_socket, buf, sizeof(buf));

и приведите массив char к типу пакета

inPacket* p = (inPacket*)buf;

Это отлично работает, у меня есть полный массив целых чисел в поле 'numbers' после приведения.Я не могу понять, почему ниже не работает, при передаче адреса, по которому я хочу сохранить числа

void func(int* out)
{
    inPacket inpacket;
    inPacket.numbers = out;
    recv(m_socket, (char*)&inpacket, sizeof(inPacket));
}

массив 'numbers' является плохим указателем после вызова recv.

Переданный массив распределяется вызывающей функцией

int numbers[10];
func(numbers);

Ответы [ 2 ]

2 голосов
/ 22 февраля 2012

То, что делает recv, копирует данные из внутреннего буфера в тот, который вы предоставляете.Таким образом, он перезаписывает содержимое вашей структуры.Вы также изменяете член массива на другой указатель, который является нет-нет.И не только это, вы пытаетесь установить для него массив, который на меньше , чем существующий массив, что может привести к recv возможному перезаписи памяти вне вашего нового массива.

Вам нужносделать что-то вроде этого:

void func(int* out, int maxnum)
{
    inPacket inpacket;
    recv(m_socket, (char*)&inpacket, sizeof(inPacket));

    memcpy(out, inpacket.numbers, sizeof(int) * maxnum);
}

Затем вы вызываете функцию следующим образом:

int numbers[10];
func(numbers, 10);

Редактировать: Если требуется динамический массив, то вызовrecv должны быть изменены вместе со структурой:

typedef struct inPacket{
    int cmd;
    int seqNo;
    int numbers[0];
} inPacket;

void func(int* out, int maxnum)
{
    size_t packetSize = sizeof(inPacket) + sizeof(int) * maxnum;
    inPacket *inpacket = malloc(packetSize);

    recv(m_socket, inpacket, packetSize);

    memcpy(out, inpacket->numbers, sizeof(int) * maxnum);

    free(inpacket);
}
0 голосов
/ 22 февраля 2012

Я предполагаю, что recv берет размер буфера и пытается его заполнить. Но размер указателя просто int, поэтому он, вероятно, просто читает несколько (4?) Байтов и отбрасывает их в буфер. Для сообщений сокетов переменного размера обычно нужно использовать некоторую структуру, которая знает, сколько байтов будет иметь получаемое сообщение (например, добавление к сообщению целого числа, равного размеру остальной части сообщения, затем выделение буфера соответствующим образом и вызов recv снова с новым буфером)

...