tags:

views:

208

answers:

3

Hi

I am trying to allocate a char array of size 1000. This array is passed to a function where it should be filled with the data that has been received from the TCP Socket. The problem occurs then when I try to delete[] buffer: Here I get as a result a User Panic 42. Unfortunately, I do not really see what is going wrong in this simple code fragement...

int main
{
 unsigned char *buffer = new unsigned char[1000];
 Recv(&buffer);

 delete[] buffer;  
 return (0);
}

void Recv(unsigned char **buffer)   
{
 TRequestStatus iStatus;
 TSockXfrLength len;

 TBuf8<1000> buff;
 iSocket.RecvOneOrMore( buff, 0, iStatus, len );  
 User::WaitForRequest(iStatus); 

 *buffer = ( unsigned char* )buff.Ptr();  
}

Thanks for any useful hints!

+2  A: 

Your array allocation is without effect because inside the function, you assign a new pointer to the array:

*buffer = ( unsigned char* )buff.Ptr();

Now the buffer points to another memory location, presumably one that you may not free using delete (e.g. one on the stack, or allocated using something other than new).

To fix the problem, it's probably best to copy the data to your array:

void Recv(unsigned char *buffer)   
{
    TRequestStatus iStatus;
    TSockXfrLength len;

    TBuf8<1000> buff;
    iSocket.RecvOneOrMore( buff, 0, iStatus, len );         
    User::WaitForRequest(iStatus);  

    unsigned char* const tmpbuf = static_cast<char*>(buff.Ptr());
    std::copy(tmpbuf, tmpbuf + len, buffer);
}

Notice that the buffer pointer is now passed directly to the function Recv, no further indirection needed since we don't manipulate the pointer directly.

Konrad Rudolph
Your "presumably" is correct, it is on the stack. TBuf8<N> contains an N-byte array.
Steve Jessop
And fwiw, the type of buff.Ptr() is TUint8*, and TUint8 is a typedef for unsigned char.
Steve Jessop
A: 

Um, you're trying to delete[] something that's not allocated by you. You're delete[]ing buff.Ptr() while leaking the array allocated in main().

Christoffer
+5  A: 

What Konrad says is true, but I don't think he knows Symbian. If you do need a function to read bytes into a char buffer, then a better fix would be:

void Recv(unsigned char *aBuffer, int aSize)   
{
    TRequestStatus iStatus;
    TSockXfrLength len;

    TPtr8 buff(aBuffer, aSize);
    iSocket.RecvOneOrMore( buff, 0, iStatus, len );         
    User::WaitForRequest(iStatus);  
}

TBuf8 is a descriptor which contains an array to hold the data. TPtr8 is a descriptor which refers to an external buffer that you specify. Either can be passed into RecvOneOrMore, since they both inherit from the parameter type, TDes8&. So the socket can be made to write its data directly into your buffer, instead of writing into a buffer on the stack and then copying as Konrad's code does.

You probably also need to check the status to detect errors, and report success/failure and the length written back to the caller.

Steve Jessop
That is exactly what I was looking for. So many thanks onebyone and the others with their helpful comments!
“… but I don't think he knows Symbian” – exactly right. +1 for the improved code.
Konrad Rudolph