Live data from Hacker News

Bugs in Hello World

blog.sunfishcode.online

161–170 of 262 posts

Re: Bugs in Hello World

#161

Even Golang de facto suffers from this. I don't think I can name a time I saw someone check the return value of fmt.Print or log.Print. Not checking the return value still seems the the "right" thing to do.

This seems to be checking return values, which is a very unixy thing to do. Most Go in the wild is doing way more than a typical *nix binary, so the use case differs. If you want a resilient system, you don't die on print and log failures.

Usually the result of ignoring "disk full" or partial writes is not resilience but byzantine failure instead.

Re: Bugs in Hello World

#162
post #134

To those perplexed by the behaviour of Java's Hello World, as Java is otherwise very careful with error handling, this is because System.out is a java.io.PrintStream, and that's its documented behaviour:[1] > Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method. So the correct Hello World would…

It's a behavioural side-effect of checked exceptions. Because IOException is a checked exception, throwing it for console output would cause a lot of pain for printf debugging.

Well, Java has since introduced RuntimeIOException, which could be used in cases where an IO exception is unexpected, so we could introduce a new class, say, ErrorCheckingPrintStream, and add the method `ErrorCheckingPrintStream withErrorChecks()` to PrintStream if it's considered sufficiently worthwhile. So you could have:

    System.out.withErrorChecks().println("Hello World!);
But we can't change the behaviour of the existing PrintStream.

Re: Bugs in Hello World

#163

Enjoyable read for sure, but i think the question whether ot not this constitutes a bug or not is open for interpretation. IMHO, it doesn't. hello.c is written in a way that makes it very clear that the program doesn't care about error conditions in any way shape or form; the return value of printf is ignored, the output isn't flushed, the return of flushing isn't checked, noone looks at errno; ...so anything happeni…

So the question boils down to: Is hello world a program that is supposed to write hello world or is it a program that is supposed to (compile and) start? For me it's usually the latter.

Re: Bugs in Hello World

#164

Correct solution: printf '#include \nint main() { return printf("Hello world!\\n") && fflush(stdout); }\n' | cc -xc - && ./a.out > /dev/full && echo "Success\!"

Shouldn’t that be

  return (printf("Hello world!\n") 
printf returns the “number of characters transmitted to the output stream or negative value if an output error or an encoding error (for string and character conversion specifiers) occurred”, so it won’t ever return zero for that call (https://en.cppreference.com/w/c/io/fprintf)

I also think this optimally should do something like

  int x = printf("Hello world!\n");
  if(x
Logging an error message to stderr should be considered, too. I would ignore any errors from that, but attempting to syslog those or to write them to the console could be a better choice.

Re: Bugs in Hello World

#166
post #163

Enjoyable read for sure, but i think the question whether ot not this constitutes a bug or not is open for interpretation. IMHO, it doesn't. hello.c is written in a way that makes it very clear that the program doesn't care about error conditions in any way shape or form; the return value of printf is ignored, the output isn't flushed, the return of flushing isn't checked, noone looks at errno; ...so anything happeni…

So the question boils down to: Is hello world a program that is supposed to write hello world or is it a program that is supposed to (compile and) start? For me it's usually the latter.

None. Hello world is a program for beginners to teach them the most basic way to debug a program. The sole purpose of hello world is to explain how to print internal state of a program. In that case the examples are correct, they succeed.

Re: Bugs in Hello World

#167

Enjoyable read for sure, but i think the question whether ot not this constitutes a bug or not is open for interpretation. IMHO, it doesn't. hello.c is written in a way that makes it very clear that the program doesn't care about error conditions in any way shape or form; the return value of printf is ignored, the output isn't flushed, the return of flushing isn't checked, noone looks at errno; ...so anything happeni…

This is a strange definition of 'buggy' to me. Surely it shouldn't depend on anything to do with the source code, otherwise closed-source programs are all 'neither-buggy-nor-not-buggy' and that can't be the case...

Re: Bugs in Hello World

#168
post #32

I’m disappointed. I expected some obscure edgecase (like “Main is usually a function…” [1]) but instead that’s about scope handling, contract design and responsibility shift. “Hello world” method simply calls an API to a text interface. It uses simple call, to a simple interface that is expected to be ever present. I don’t find any bug there. It won’t work if such interface isn’t available, is blocked or doesn’t exis…

I also had higher expectations after reading the title and was disappointed when I realized it was about failure to handle all possible system call results. I thought it was gonna be a bug in the C standard library or something.

I still agree with the author though. This is a serious matter and it seems most of the time the vast amount of complexity that exists in seemingly simple functionality is ignored.

Hello world is not "simply" calling a text interface API. It is asking the operating system to write data somewhere. I/O is exactly where "simple" programs meet the real world where useful things happen and it's also where things often get ugly.

Here's all the stuff people need to think about in order to handle the many possible results of a single write system call on Linux:

  long result = write(1, "Hello", sizeof("Hello") - 1);

  switch (result) {
    case -EAGAIN:
      /* Occurs only if opened with O_NONBLOCK. */
      break;
    case -EWOULDBLOCK:
      /* Occurs only if opened with O_NONBLOCK. */
      break;
    case -EBADF:       
      /* File descriptor is invalid or wasn't opened for writing. */
      break;
    case -EDQUOT:
      /* User's disk quota reached. */
      break;
    case -EFAULT:
      /* Buffer points outside accessible address space. */
      break;
    case -EFBIG:
      /* Maximum file size reached. */
      break;
    case -EINTR:
      /* Write interrupted by signal before writing. */
      break;
    case -EINVAL:
      /* File descriptor unsuitable for writing. */
      break;
    case -EIO:
      /* General output error. */
      break;
    case -ENOSPC:
      /* No space available on device. */
      break;
    case -EPERM:
      /* File seal prevented the file from being written. */
      break;
    case -EPIPE:
      /* The pipe or socket being written to was closed. */
      break;
  }
Some of these are unlikely. Some of these are irrelevant. Some of these are very important. Virtually all of them seem to be routinely ignored, especially in text APIs.

Re: Bugs in Hello World

#169

You all joke that this doesn’t happen in practice, but something like this literally just bit me and it took me a few too many minutes to figure out what was going on. I use a bash script as my BROWSER which calls another bash script to launch or communicate with my browser that I run inside a container. The script that my BROWSER script calls has some debug output that it prints to stderr. I use mutt as my email cli…

> some other people disagree and say you should never use `set -e` outside of development

I'm really interested. What are their arguments? And how do they handle errors?

Post reply on HN