user1641774
user1641774

Reputation:

Writing to file writes garbage on top of what I want

I have the code below:

#include <stdio.h>
#include <unistd.h>

int main () {

    int fd = open("filename.dat", O_CREAT|O_WRONLY|O_TRUNC, 0600);
    int result = write(fd, "abcdefghijklmnopqrstuvxz", 100);
    printf("\n\nfd = %d, result = %d, errno = %d", fd, result, errno);
    close(fd);
    return 0;
}

I am trying to understand what happens when I try to write more bytes to a file than I have available. So I am calling write and asking the program to write 100 bytes while I have much less than that. The result: a bunch of stuff from stdout ends up on filename.dat. If instead of 100 I use strlen("abcdefghijklmnopqrstuvxz"), I get the desired result. My question then is: why is the program trying to write beyond the '\0' character on my string? Is there some undefined behavior going on here?

Upvotes: 1

Views: 1630

Answers (5)

NovaDenizen
NovaDenizen

Reputation: 5325

I think that the basic issue here is that you're thinking of C strings as values, you think you're passing this value to the write function, and the write function is writing out your value plus extra junk.

C is lower level than that. In C, we don't really pass strings around, instead we pass pointers to strings, which are 'char *' values but with the added promise that they point to a valid block of memory that should be treated as a null-terminated string.

The write() function doesn't care about the null-terminated string convention. The parameters in the write call provide a file descriptor, a char *, and a buffer length.

Also, the compiler converts string constants into const char arrays. The equivalent of this happens at the top level:

const char *stringconst00001[27] = { 'a', 'b', 'c', ... 'y', 'z', '\0' }

And it does this in main():

int result = write(fd, stringconst00001, 100);

Upvotes: 0

Nucc
Nucc

Reputation: 1031

Because there are two techniques to represent a string. There is the null-terminated version, and there is another when you define its size and the pointer to the first byte. Write uses the second one. It needs a pointer where your data begins and a length to know how much data should copy to the file, but it doesn't see the null values. Sometimes these methods wraps a simple memcpy.

So when you defined the 100 length, in the memory after your abcdefghijklmnopqrstuvxz the program stored your "bunch of stdout stuff". That's why you see garbage. You were lucky because you can get SEGFAULT easily in these cases!

Upvotes: 0

heretolearn
heretolearn

Reputation: 6555

The write() function you are using does not care about the content. It just writes the no. of bytes you tell it to write in the file.

So when you say it to write 100 bytes and provide less than 100 bytes. The remaining bytes are taken as garbage value.

But when you are using strlen("abcdefghijklmnopqrstuvxz"), you are asking the write() to write bytes equal to the length of the string. So it works fine there

Upvotes: 0

huseyin tugrul buyukisik
huseyin tugrul buyukisik

Reputation: 11926

My question then is: why is the program trying to write beyond a \0 Because you want it to write 100 chars.

Is there some undefined behavior going on here? If you increase that 100 to a large number and if that area is on a non-privilage area, it is undefined behaviour.

Upvotes: 0

cnicutar
cnicutar

Reputation: 182744

My question then is: why is the program trying to write beyond the '\0' character on my string?

The function write(2) doesn't care about 0-terminators. It actually doesn't care about buffer contents at all: it will try to write as many bytes as you tell it.

Is there some undefined behavior going on here

Of course, trying to write more than you have might incur the wrath of the OS who could decide to terminate your process if it touches inaccessible memory.

Upvotes: 3

Related Questions