views:

1106

answers:

4

Hey,

When receiving data through a socket using recv, I've noticed that, with:

char buffer[4];
memset(buffer, 0, 4);
recv(socket, buffer, 4, 0);

I receive

mesgx��

"mesg" being what I sent, with some random characters appended.

If I use

char * method = (char *) malloc(4);
memset(buffer, 0, 4);
recv(socket, buffer, 4, 0);

instead, I receive

mesg

So there's no random stuff appended to my string. I figured out that if I use char[5] instead it works as well, but I do not really understand why. Does malloc(4) really allocate 5 bytes, the fifth being a NUL?

Regards,
x3ro

+5  A: 

You need 5 characters to be properly NULL terminated. The terminating NULL counts as one, so if we need N characters, allocate N+1. Or conversely, for an allocation of N you have N-1 available for your content.

Dirk Eddelbuettel
I thought as much, but why does it work with malloc then?
x3ro
+10  A: 

The call to malloc(4) really only allocates four bytes. It was just coincidence that the next byte in memory happened to be a NUL, which terminated your string for you.

In the case where you allocated char buffer[4] on the stack, the next byte happened to be an 'x' followed by some other stuff, so your string just continued until it found the next NUL byte.

Socket functions deal with bytes only, and don't treat the bytes as strings with a trailing NUL or anything extra. You get exactly what you ask for.

Greg Hewgill
+2  A: 

You can't possibly have received more that 4 chars as you only asked recv for a maximum of 4 bytes to be placed into your buffer. You should check the return value of recv to see how many bytes were actually returned.

I suspect that the issue is that you are not being careful to only output 4 chars from whatever routine is generating the output. One way of displaying the initial contents of a possibly non-null terminated char buffer is this.

printf("%.4s\n", buffer);

A complete recv call snippet might be:

#define MAX_BUF_LEN (512)
char buffer[MAX_BUF_LEN];
ssize_t count = recv(socket, buffer, MAX_BUF_LEN, 0);

if (count > 0)
    printf("%.*s\n", count, buffer);
Charles Bailey
+3  A: 

I suspect the difference is a coincidence. When you use buffer as a string, for example in printf(), it will be read past it's limit until a '\0' is found.

You should use buffer[5] or malloc(5) in both cases. The memset() shouldn't be necessary, better put a buffer[4] = '\0' after the recv().

Henk Holterman