Home > OS >  System call read result display random characters after the result
System call read result display random characters after the result

Time:06-01

I've recieved this assignment where I have to read from a file.txt(max size 4096B) four times, basically splitting it in 4 strings of equal size. I have to fill this structure(just consider field 'msg', i think the problem is there):

struct message {
    
    long mtype
    int nclient; 
    int pid;     
    char path[151];
    char msg[1025];
};

I used an array of 4 struct message to store all 4 parts

This is my read:

struct message msgs[4];
    for (int i = 0; i < 4; i  ) {
        msgs[i].nclient=pos 1;
        msgs[i].mtype = 42;
        msgs[i].pid = getpid();
        strcpy(msgs[i].path, filespath[pos]);
        if (read(fd, msgs[i].msg, nMsgSize[i]) == -1)
            ErrExit("read failed");
        printf("I've read: %s\nMSGSize: %d\nPath: %s\n",msgs[i].msg, nMsgSize[i], msgs[i].path);
    }

I tested it on a file "sendme_5.txt" that has this text in it:

ABCD

And this is my output:

I've read: A MSGSize: 1 Path: /home/luca/Desktop/system_call_meh/myDir/joe_bastianich/bruno_barbieri/sendme_5.txt

I've read: BP"�> MSGSize: 1 Path: /home/luca/Desktop/system_call_meh/myDir/joe_bastianich/bruno_barbieri/sendme_5.txt

I've read: C#��;�U MSGSize: 1 Path: /home/luca/Desktop/system_call_meh/myDir/joe_bastianich/bruno_barbieri/sendme_5.txt

I've read: D�.�>� MSGSize: 1 Path: /home/luca/Desktop/system_call_meh/myDir/joe_bastianich/bruno_barbieri/sendme_5.txt

If i try to read the full file without dividing it in 4(with only one read), it displays it correctly.

The problem started when i changed the field char path[151]. We had to set the max size to 151 from PATH_MAX(4096) after a change in the assignment, but i dont know if it's related.

What is the problem here?

CodePudding user response:

As stated above, read does not know what a null-terminated string is. It deals with raw bytes, making no assumptions about the data it reads.

As is, your strings are possibly not null-terminated. printf("%s", msgs[i].msg) might continue past the the end of the read data, possibly past the end of the buffer, searching for a null-terminating byte. Unless the data read happens to contain a null-terminating byte, or the buffer was zeroed-out beforehand (and not completely filled by read), this is Undefined Behaviour.

On success, read returns the number of bytes read into the buffer. This may be less than requested. The return value is of type ssize_t.

When using this system call to populate string buffers, the return value can be used to index and place the null-terminating byte. An additional byte should always be reserved for this case (that is, always read at most the size of the buffer minus one: char buf[256]; read(fd, buf, 255)).

Always check for error, or the return value of -1 will index the buffer out-of-bounds.

Assuming nMsgSize[i] is the exact size of the msgs[i].msg buffer:

ssize_t n;
                                                            
if (-1 == (n = read(fd, msgs[i].msg, nMsgSize[i] - 1)))
    ErrExit("read failed");
    
msgs[i].msg[n] = 0;
    
printf("READ:%zd/%d expected bytes, MSG:<<%s>>\n", n, nMsgSize[i] - 1, msgs[i].msg);
  • Related