开发者

Gibberish in read() buffer?

I am new to C, and so I am completely confused by the following behavior. Using pipe() and fork() I am reading the output of the following trivial ruby program:

puts "success"

via a call to the read function in C:

n = read(fd[0], readbuffer, sizeof(readbuffer));
printf("received: %s", readbuffer);

However, printf is printing a bunch of those 'unrecognised character' symbols (like the question mark in a diamond) to the console. Furthermore, doing a comparison like:

    if (strcmp(readbuffer, "success") == 0)
    {
        /* do something */
    }

fails. What am I doing wrong?

Edit: Declarations as requested. I have no idea about memsetting, my first day in C.

int fd[2], in;
pid_t pid;
char readbuffer[6];

Edit:

The answer by 'mu is too short' also solves the problem. The consensus seems to be that using memset is overkill. I am a novice C programmer so I will have to believe开发者_如何学C the commentors' opinions. This is, however, argumentum ad populum and mu is too short may indeed be more in the right. In any case, I recommend a reading of both answers as any 'overkill' is probably still trivially so.


As others have pointed out, your buffer isn't big enough to hold the text you're reading, and you don't ensure it's null terminated.

But using memset() to zero the entire buffer before each read is unnecessary; you just need to ensure that there's a null at the end of data you've read (and make your buffer bigger of course).

If you make readbuffer at least 9 characters long, and replace:

n = read(fd[0], readbuffer, sizeof(readbuffer));

..with..

n = read(fd[0], readbuffer, sizeof(readbuffer) - 1);
readbuffer[n] = '\0';

..then that should do it (though you should ideally check that n is >= 0 to make sure the read() succeeded). Specifying one less than the size of the read buffer ensures that readbuffer[n] won't overrun (but if read() failed it could underrun).

Then you'll just have to deal with the linefeed at the end.

This also assumes that the entire string is read in one read call. It's likely in this case, but often when using read its necessary to concatenate multiple reads until you've read enough of the data.


As I understand it, your line:

puts "success"

will output (in C-terms)

success\n\0

which I count as 9 characters.

You declared readbuffer as only 6. The previous answer only upped it to 7.


As the comments note, you won't have a null terminator on readbuffer so it isn't really a C string. You could do this:

#include <string.h>

/* ... */

memset(readbuffer, 0, sizeof(readbuffer));
n = read(fd[0], readbuffer, sizeof(readbuffer) - 1);

That will give you a proper null terminated string. But, if you actually want a string of length 6, then change the declaration of readbuffer to:

char readbuffer[7];

If you only need your readbuffer once, you could say:

char readbuffer[7] = { 0 };

to initialize it to all zeros. However, if you're doing the read in a loop then you'll want to memset(readbuffer, 0, sizeof(readbuffer)) before each read to make sure you don't end up with any leftover data from the last step.

C won't automatically initialize a local variable, you have to do it yourself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜