I did my own Socket class, to be able to send and receive HTTP requests.
But I still got some problems. The following code (my receive function) is still buggy, and crashing sometimes.
I tried debugging it, but it must be somewhere in the pointer arithmetics / memory management.
int Socket::Recv(char *&vpszRecvd)
{
//vpszRecvd = NULL;
int recvsize = 0;
char TempBuf[1024];
int Result = 0;
char* temp;
do
{
memset(TempBuf, 0, sizeof(TempBuf));
Result = recv( this->sSocket, TempBuf, sizeof(TempBuf) -1, 0 );
if (recvsize == 0)
recvsize = Result;
if ( Result > 0 )
{
if ( vpszRecvd != NULL )
{
if (temp == NULL)
{
temp = (char*)calloc(recvsize + 1, sizeof(char));
}
else
{
realloc(temp, recvsize + 1);
}
if (temp == NULL)
return 0;
memcpy(temp, vpszRecvd, recvsize);
realloc(vpszRecvd, recvsize + Result);
if (vpszRecvd == NULL)
return 0;
memset(vpszRecvd, 0, recvsize + Result);
memcpy(vpszRecvd, TempBuf, Result);
memcpy(vpszRecvd + recvsize, TempBuf, Result);
recvsize += Result;
}
else
{
realloc(vpszRecvd, Result);
if (vpszRecvd == NULL)
return 0;
memset(vpszRecvd, 0, Result);
memcpy(vpszRecvd, TempBuf, Result);
recvsize += Result;
}
}
else if ( Result == 0 )
{
return recvsize;
}
else //if ( Result == SOCKET_ERROR )
{
closesocket(this->sSocket);
this->sSocket = INVALID_SOCKET;
return SOCKET_ERROR;
}
}
while( Result > 0 );
return recvsize;
}
Does anybody see anything that could cause the crash, or does anyone have a better / faster / smaller and stable example how to receive a full packet via recv()?
I can’t use strings, it must be done with chars, though.
Thanks for your help.
You don’t initialise
tempand, on top of that, your call toreallocis wrong. It should be:When you call
reallocas you have, you throw away the new address and there’s a good chance that the old address has now been freed. All bets are off when you then try to dereference it.The reason
reallocreturns a new address is because expansion of the buffer may necessitate it being moved if that current block is surrounded in the memory arena (in other words, it can’t just expand into a free block following it). In that case, a new block will be created in the arena, the contents transferred from the old block and the old block freed. You have to get the return value fromreallocin case that happens.Keep in mind that
reallocdoesn’t have to return a new pointer, it may give you the same pointer if, for example, there was enough free space after the block to satisfy the new size or if you’re reducing the size.It can also return NULL if it can’t expand the block, you should watch out for that as well, especially since:
will result in a memory leak when it returns NULL (it doesn’t free the old block).
A few other things:
calloc, especially in this case since you’re copying over the memory anyway.memseta memory chunk to 0 if you’re immediately going tomemcpyover it.temptoNULL, you can just usereallocwithout testing it. That’s becauserealloc(NULL,7)is identical tomalloc(7)–reallocis perfectly capable of starting with a null pointer.calloc, this is for education only –sizeof(char)is always 1 by definition.Why don’t we start with something a bit simpler? Now, this is totally from my head so there may be some bugs but it’s at least cut down from the memory-moving behemoth in the question 🙂 so should be easier to debug.
It’s basically broken down into:
and the code looks like this: