c - recv pakker med peger medlemmer

Indlæg af Hanne Mølgaard Plasc

Problem



Når jeg modtager en indgående msessage, modtager jeg et korrekt resultat, når min pakkestruktur har en fast størrelse array i den, som denne


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


så kalder jeg recv sådan


char buf[1024];
recv(m\_socket, buf, sizeof(buf));


og kast char array til pakketype


inPacket* p = (inPacket*)buf;


Dette virker fint, jeg har et komplet udvalg af ints i feltet 'numre' efter støbning. Jeg kan ikke forestille mig, hvorfor nedenstående ikke virker, når de passerer i en adresse, hvor jeg vil gemme tallene


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


'Nummer' array er en dårlig pointer efter opkaldet til recv.


Arrayet, der sendes ind, er allokeret af den kaldende funktion


int numbers[10];
func(numbers);

Bedste reference


Hvad recv gør er, det kopierer data fra en intern buffer til den, du leverer. Så det overskriver indholdet af din struktur. Du ændrer også arraymedlemmet til en anden peger, hvilket er et nej-nummer. Og ikke kun det, du forsøger at indstille det til et array, der er mindre end det eksisterende array, hvilket kan føre til, at recv muligvis overskriver hukommelse uden for dit nye array.


Du skal gøre noget som dette:


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

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


Så kalder du funktionen som denne:


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


 Hvis et dynamisk array ønskes, skal opkaldet til recv ændres sammen med strukturen:


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);
}

Andre referencer 1


Mit gæt er, at recv tager størrelsen af ​​bufferen, og forsøger at udfylde den. Men størrelsen på en peger er bare en int, så det læser nok bare nogle få (4?) Bytes og slam dem i bufferen.
For stikkontakter med variabel størrelse skal man som regel bruge en struktur, der ved, hvor mange byte meddelelsen skal modtage (som at forberede beskeden med en int, som er størrelsen på resten af ​​meddelelsen, derefter tildele bufferen tilsvarende og ringe til recv igen med den nye buffer)