Search code examples
c++udppacketgo-back-n

Segmentation fault (core dumped) when trying to send a packet that contains a character array


Trying to send a packet that contains up to 30 characters along with other identifying information. Here is the constructor.

packet::packet(int t, int s, int l, char * d){
type = t;
seqnum = s;
length = l;
data = d;
}

For my class we're required to serialize and deserialize via:

void packet::serialize(char * spacket){
sprintf (spacket, "%d %d %d %s", type, seqnum, length, data);   
}

void packet::deserialize(char * spacket){
char * itr;
itr = strtok(spacket," ");
char * null_end;

this->type = strtol(itr, &null_end, 10);

itr = strtok(NULL, " ");
this->seqnum = strtol (itr, &null_end, 10);

itr = strtok(NULL, " ");
this->length = strtol (itr, &null_end, 10);

if(this->length == 0){
    data = NULL;
}
else{
    itr = strtok(NULL, " ");    
    for(int i=0; i < this->length; i++){ // copy data into char array
        this->data[i] = itr[i];
    }
  }
}

This client code causes my server.exe to have a segmentation fault:

char sendPayload[512];
char receivePayload[512];
char sendBuffer[30] = {'1', '2', '3', '\0'};
int receivedPacketType = 0;
int sendPacket;
int receivePacket;

bzero(receivePayload, 512);
bzero(sendPayload, 512);

for (int iterator = 0; iterator < 8; iterator++)
{
    //Setting up sendPayload for sending.
    packet sendpckt(1, iterator, strlen(sendBuffer), sendBuffer);
    sendpckt.serialize((char*)sendPayload);

    //Datagram send to emulator.
    sendPacket = sendto(sendSocket, &sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);

    //Datagram wait on receive from emulator.
    receivePacket = recvfrom(receiveSocket, &receivePayload, sizeof(sendPayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen);

    //Setting up packet for receivePayload.
    packet recvpckt(0,0,0,NULL);
    recvpckt.deserialize((char*)receivePayload);
    recvpckt.printContents();

    bzero(receivePayload, 512);
    bzero(receivePayload, 512);

}

Here is the server side receiving code:

char receivePayload[512];
char sendPayload[512];
int expectedSeqNum = 0;
int receivedPacketType = 0;
int receivedPacketSeqNum = 0;
int receivedPacketLength = 0;
char receivedPacketData[512];
int receivePacket;
int sendPacket;
std:string finalText;

bzero(receivePayload, 512);
bzero(sendPayload, 512);

do
{
    receivePacket = recvfrom(receiveSocket, &receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen);
    packet recvpckt(0, 0, 0, NULL);
    recvpckt.deserialize((char*)receivePayload);
    receivedPacketType = recvpckt.getType();
    receivedPacketSeqNum = recvpckt.getSeqNum();
    receivedPacketLength = recvpckt.getLength();
    bzero(receivePayload, 512);
    recvpckt.printContents();

    if (receivedPacketType == 3)
    {
        break;
    }

    /*
    if (receivedPacketType == 1)
    {
        *receivedPacketData = *recvpckt->getData();
        printf("%s\n", receivedPacketData);
    }
    */

    if (receivedPacketSeqNum == expectedSeqNum)
    {
        packet sendpckt(0, expectedSeqNum, 0, NULL);
        sendpckt.serialize((char*)sendPayload);
        sendPacket = sendto(sendSocket, &sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
        bzero(sendPayload, 512);
        expectedSeqNum = expectedSeqNum + 1;
        if (expectedSeqNum > 7)
        {
            expectedSeqNum = 0;
        }

    }
    else
    {
        packet sendpckt(0, expectedSeqNum, 0, NULL);
        sendpckt.serialize((char*)sendPayload);
        sendPacket = sendto(sendSocket, &sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
        bzero(sendPayload, 512);
    }

} while (1);

If I null the contents of the data in the packet and set the length to 0, packets get transferred perfectly fine. As soon as I try to increase the length of the packet and give it a string the server experiences a segmentation fault.

What am I missing here? I feel like I'm making my buffers too big or maybe I'm pointing or referencing something incorrectly.


Solution

  • You initialize your receive packet (recvpckt) like this:

    packet recvpckt(0, 0, 0, NULL);
    

    Which makes the data member NULL.

    Then you call recvpckt.deserialize, which writes to the uninitialized data array. You need to have a memory allocation somewhere (e.g. in recvpckt.deserialize), or else pass the address of an array to the recvpckt constructor to write the data into.

    This kind of problem is best solved with the use of a debugger.