Live data from Hacker News

Bugs in Hello World

blog.sunfishcode.online

31–40 of 262 posts

Re: Bugs in Hello World

#31

This raises an interesting question: is there any IO function that should return unit/void? Or equivalently are there any IO functions for which we can safely ignore the return value/ignore all exceptions? It seems like every single IO thing I can think of can have a relevant error, regardless of whether it's file-system related, network, or anything else.

In C, and many other languages, the file stream error state is saved after each operation, so you can skip error checking on every output line and only do

  if (fflush(stdout) != 0 || ferror(stdout) != 0)
  {
    perror("stdout");
    return EXIT_FAILURE;
  }
at the end of the program. The same should be done for stderr as well.

In GNU programs you can use atexit(close_stdout) to do this automatically.

Re: Bugs in Hello World

#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 exist. It won’t work on my coffee grinder nor on my screwdriver. It won’t work on my Arduino because there is no text interface neither.

Of course, one could argue that user might expect you to handle that error. That’s all about contracts and expectation. How should I deal with that? Is the “Hello world” message such important that the highest escalated scenario should be painted on the sky? I can imagine an awkward social game where we throw each other obscure challenges and call it a bug.

It’s nitpicking that even such simple code might fail and I get it. It will also fail on OOM, faulty hardware or if number of the processes on the machine hit the limit. Maybe some joker replaced bindings and it went straight to 3D printer which is out of material? _My expectations_ were higher based on the title.

Now allow me to excuse myself, I need to write an e-mail to my keyboard manufacturer because it seems like it has a bug which prevents it from working when slightly covered in liquid coffee.

[1]: http://jroweboy.github.io/c/asm/2015/01/26/when-is-main-not-...

Re: Bugs in Hello World

#33
post #22

And to catch such a thing in C, if anyone was wondering, you would have to fflush stdout.

This is true, however if we modify the program to print a 4096-byte long string instead of just the "hello world" string, then it's not sufficient again. And of course, the number 4096 is system-dependent. So to really do hello world in C right, in addition to fflush, you also need to check the return value from puts. I've never seen any C tutorial do that though.

Because errors on FILE streams are persisted until clearerr, it should be sufficient to check the return value of fflush at the end of the program. Presumably the FILE I/O interface was deliberately designed this way, so error checking could be consolidated at the end of a series of operations.

Re: Bugs in Hello World

#34

Imo this is because the responsibility is not clearly defined and can be argued upon. If my program writes to the standard output, but you choose to redirect the pipe to a different location, is it my program’s responsibility to check what happens to the bytes AFTER the pipe? After all: my program did output everything as expected . The part which fucked up was not part of my program. I can see why some projects deci…

I thought about this too a bit just now. But I think it's not the shell setting up stuff outside your process that then fails. Rather you already get handles to the "full" file system at process creation and then it's your problem. And traditionally, the behaviour you get from all the standard streams is very unpredictable, depending on where they point.

Re: Bugs in Hello World

#35
post #11

It's a good post, but heavily OS dependant. For example, on my Mac: $ ls /dev/null /dev/full ls: /dev/full: No such file or directory /dev/null I guess in theory, you can imitate `/dev/full` by other means.

>Linux has this fun device file called "/dev/full" Yes it is. And it specifies the OS as well.

NetBSD and FreeBSD have /dev/full as well.

Re: Bugs in Hello World

#36
> There's our "No space" error getting reported by the OS, but no matter, the program silently swallows it and returns 0, the code for success. That's a bug!

Bzzt, no. You can't say that without knowing what the program's requirements are.

Blindly "fixing" a program to indicate failure due to not being able to write to standard output could break something.

Maybe the output is just a diagnostic that's not important, but some other program will reacts to the failed status, causing an issue.

Also, if a program produces output with a well-defined syntax, then the termination status may be superfluous; the truncation of the output can be detected by virtue of that syntax being incomplete.

E.g. JSON hello world fragment:

   puts("{\"hello\":\"world\"}");
   return 0;
if something is picking up the output and parsing it as JSON, it can deduce from a failed parse that the program didn't complete, rather than going by termination status.

Re: Bugs in Hello World

#37
post #17

It's a fun take, but a hyperbole nonetheless. hello.c is supposed to be run from a terminal and write back to it: there's always space to write. It's not meant to be part of a shell script, so the error status is irrelevant. It does show that we take such examples a bit too literally: our feeble minds don't consider what's missing, until it's too late. That's a didactic problem. It only matters to certain kinds of so…

It depends on whether you want your Hello World programs to reflect an actual program or just be an approximation.

I’d argue there is little benefit in the latter. Particularly these days where the Hello World of most imperative languages look vaguely similar. Maybe back when LISP, FORTRAN and ALGOL were common it was more useful showing a representation of the kind of syntax one should expect. But that isn’t the case any more.

Plus given the risk of bugs becoming production issues or, worse, security vulnerabilities and the ease and prevalence of which developers now copy and paste code, I think there is now a greater responsibility for examples to make fewer assumptions. Even if that example is just Hello World.

Re: Bugs in Hello World

#38
post #22

And to catch such a thing in C, if anyone was wondering, you would have to fflush stdout.

This is true, however if we modify the program to print a 4096-byte long string instead of just the "hello world" string, then it's not sufficient again. And of course, the number 4096 is system-dependent. So to really do hello world in C right, in addition to fflush, you also need to check the return value from puts. I've never seen any C tutorial do that though.

What would be the expected reaction if either puts or fflush returns an error code? You might think, write a message on stderr (which may be different from stdout), but what if stderr is also redirected to a full device? How would you react to the error code returned from that?

To me this is an indication that you need to know the context in which the program gets run, and its purpose in that context. Or you'd have to specify every edge case, but I've never seen that really work in practice.

Re: Bugs in Hello World

#39

This is one of the reasons zig doesn't have a print function and you have to deal with the error when using the stdout writer[0]. [0] https://zig.news/kristoff/where-is-print-in-zig-57e9

Came here to say the same. Zig gets it right. https://ziglang.org/documentation/master/#Hello-World

Re: Bugs in Hello World

#40
post #2

Well that's precisely the mindset of C/C++. You have to think by yourself about everything that can go wrong with your code. And, man, lots of things can go wrong. I find more modern languages so much less exhausting to use to write correct code.

In this case, I don't see how they help.

A modern language could automatically throw an exception if the string cannot be completely written to standard output.

But that has not necessarily helped. The program now has a surprising hidden behavior; it has a way of terminating with a failed status that is not immediately obvious.

If it is used in a script, that could bite someone.

In Unix, there is such an exception mechanism for disconnected pipes: the SIGPIPE error. That can be a nuisance and gets disabled in some programs.

Post reply on HN