Electra Chong
Electra Chong

Reputation: 35

Why does my write function to print a string (to stdout) append random characters to output?

I'm working on an exercise for Holberton School. This is my code for 3-hello_write:

#include <unistd.h>

int main(void)
{
  write(1, "Hello, C\n", 1000);
  return (0);
}

This is the output for gcc -Wall 3-hello_write.c && ./a.out:

$ gcc -Wall 3-hello_write.c && ./a.out
Hello, C
@44v4
     zRx
       ?HQc??h?i??i?? $

When the output I want is just:

$ gcc -Wall 3-hello_write.c && ./a.out
Hello, C
$

I'm a beginner to C so I referenced this document for the syntax for the write function. http://codewiki.wikidot.com/c:system-calls:write

Is there some context I can be given as to why it might print the extra characters after my string?

Upvotes: 2

Views: 5340

Answers (5)

chrisgotter
chrisgotter

Reputation: 393

as @anT said, write appears to be trying to write a full 1000 chars to the screen. To solve this problem, you have several options, one would be to simply figure out the total length of the string you would like to print and use that in place of 1000.

#include <unistd.h>
#include <string.h>
int main(void)
{
  char *test1 = "test test test";
  char *test2 = "test test test";
  write(1, test1, strlen(test1));
  write(1, test2, strlen(test2));
  return (0);
}

That said, I sincerely doubt that your instructor would have asked you to use write. I would suggest you look into puts,

int puts( const char *str );

or the venerable printf

int printf( const char *restrict format, ... );​

These are much more commonly used, especially in introductory courses. Furthermore, using these you can streamline the process significantly.

Example:

#include <stdio.h> //both puts and printf functions are defined in this library
int main(void)
{
  char *test1 = "test test test";
  char *test2 = "test test test";
  printf(test1);
  puts(test2);
  return (0);
}

Upvotes: 1

chqrlie
chqrlie

Reputation: 144695

The function call:

write(1, "Hello, C\n", 1000);

Causes the system to write 1000 bytes from the C string starting at "Hello, C\n"... You are reading bytes beyond the end of the C string, and writing those to the terminal, all the way to the 1000th. Undefined behavior, but visibly no crash, just the C string, its '\0' terminator and whatever contents happens to be in memory after the C string.

The should specify the length of the string:

write(1, "Hello, C\n", strlen("Hello, C\n"));

Or using the size of the constant less the final '\0':

write(1, "Hello, C\n", sizeof("Hello, C\n") - 1);

Upvotes: 1

AnT stands with Russia
AnT stands with Russia

Reputation: 320401

You are supposed to tell *nix write function how many characters (bytes) from your buffer you want to write (the last parameter). You supplied a buffer of size 10 (your "Hello, C\n" string), but then asked write to write 1000 bytes. This just does not make sense.

write compliantly wrote the content of your buffer (10 characters) and then proceeded to write 990 more bytes of whatever garbage was residing in memory after your "Hello, C\n" string. That garbage is what you see in the output. Or, maybe, this is not really "garbage" bot some other, quite meaningful data, which nevertheless you have no business accessing in this way (i.e. by overrunning the boundary of some buffer).

The character count you supply as the last parameter of write should be less or equal to the size of the buffer. By specifying a greater value you are essentially lying to write. The output you see is a consequence of that lie.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726499

The best way to figure out what's wrong is to look at the documentation of the write function, and check what each individual argument controls:

ssize_t write(int fd, const void *buf, size_t count);

You are passing 1 for the file descriptor (fine), a string literal, which is a pointer to C string for the buf (also fine), and a number of characters to be written.

Note that write does not stop upon reaching the end of the string marker (i.e. '\0' at the end of the string). That is why you get undefined behavior with additional characters printed.

Passing the correct length would fix this problem:

write(1, "Hello, C\n", 9);

Unfortunately, this code is fragile, because changing the string literal requires updating its length. A better approach is to make "Hello, C\n" a constant, and use strlen:

const char *str = "Hello, C\n";
write(1, str, strlen(str));

Upvotes: 3

Vicente Cunha
Vicente Cunha

Reputation: 205

As it has been pointed out, it is because of your write function third argument: the number of bytes to write. To avoid future cases of this error, I would suggest using strlen to compute the number of bytes to be sent, like so:

#include <unistd.h>
#include <string.h>

int main(void)
{
    char buf[] = "Hello, C\n";
    write(1, buf, strlen(buf));
    return (0);
}

Upvotes: 2

Related Questions