3 ms·
Do you error check printf? I don't - the default behavior of simply ignoring I/O failures if, say, stdout's pipe was broken is usually what I want. In fact, I
by MaulingMonkey 7y ago
Do you error check printf?
I don't - the default behavior of simply ignoring I/O failures if, say, stdout's pipe was broken is usually what I want. In fact, I've had bugs in exception throwing languages where such stdout write failures threw, and I failed to explicitly catch and ignore them.
I also may skip error checking malloc. A null pointer exception / sigsegv / access violation "must" be fine if malloc is failing - even if I handle it nonfatally in our code, some of our closed source middleware doesn't, and neither do some system libraries. At best I can make slightly better fatal error messages for a subset of the resulting failures. If I'm trying to build super reliable software, I need to avoid exhausting/fragmenting memory badly enough for malloc to fail in the first place.
I have a decent chance of checking fork() for failure as I'm on the more paranoid end of error checking. I've seen enough weird junk like SetCurrentDirectory on a real directory failing due to NTFS filesystem corruption leading to an infinite loop - that I assume all documented error conditions will eventually occur somehow, as well as some undocumented ones.
But I've never seen it fail, and I'm probably just going to make it a fatal error.
- DoofusOfDeath 7y agoI typically don't check the return code of `printf`, but for the same reason you state: I've looked at its failure modes, and decided that awareness of the failure wouldn't impact my desired flow of the code. I rarely use `malloc`, but I typically do check its return code. That's because in my experience, hunting down the root cause of segfaults can be a hassle, so I prefer to write code that will fail fast on failed memory allocations.
- MaulingMonkey 7y agoFor most programmers starting out, I imagine they didn't even realize printf could fail. I certainly didn't initially. > That's because in my experience, hunting down the root cause of segfaults can be a hassle, so I prefer to write code that will fail fast on failed memory allocations. This is a great reason to add error checking. I've spent enough time hunting down harder dangling pointers and memory corruption bugs that alloc-returned-nullptr segfaults are trivial/second nature for me to figure out 99% of the time. There is that remaining 1% of cases, for the already rare scenario where malloc has failed. Quite niche... but sometimes motivation enough for me to go through with adding error checking anyways. Especially if I actually encounter it.
- jiveturkey 7y ago> Do you error check printf? If a failure would lead to data corruption, then yes. That this is important is made clear with gcc+glibc's _FORTIFY_SOURCE macro, which (e.g.) forces you to check the return value of sprintf() among others. Of course, it's hard to imagine a case where printf() is part of a data pipeline that could be corrupted. So, nominally the answer is a simple `no'. But it's a bad question, since fork() and printf() failures have different consequences. Also, boilerplate code for printf() never shows using the return value, whereas boilerplate for fork() always shows that. Your malloc() example is much better. If malloc() failure leads to corruption, you'd better check the return value. Otherwise, sure, ignore it and let your prog just die is fine! Until it isn't ...
- MaulingMonkey 7y ago> That this is important is made clear with gcc+glibc's _FORTIFY_SOURCE macro, which (e.g.) forces you to check the return value of sprintf() among others. It's worth noting that "printf" specifically does not appear to be affected by _FORTIFY_SOURCE if the documentation I'm reading is to be believed. > But it's a bad question, since fork() and printf() failures have different consequences. Pointing out there are differences - via visceral example that likely hits close to home in your own practice as a programmer - is the entire point of the question, so I'll call it a good one ;) The implicit point I'm making is that it's more complicated than "all syscalls must have error handling!" - which raises the question of, well, what does drive the choice anyways?. Ideally, perhaps a carefully reasoned consideration of the differing consequences you've pointed out. Or perhaps more likely, an adherence to examples and inertia. Or perhaps even more likely, a gut call based on things like "can I even think of when this might fail?", which one might answer "no" to - for having not yet developed a sufficiently mischevious imagination. Regardless - having established the possible existence of nuance - this then lets us properly examine if our documentation does indeed properly prepare us to make these decisions, and how useful posts like the article might be for filling in where our documentation may have failed us. > Also, boilerplate code for printf() never shows using the return value, whereas boilerplate for fork() always shows that. Boilerplate for fork() does not always show that. As a concrete counterexample, the first google hit for "fork example" lacks error handling in any of their examples, although they at least mention the possibility of negative return values. I'll avoid linking it in an attempt to avoid improving it's undeservedly high search ranking, but if you're performing the search yourself, it's on the "geeks for geeks" website. Maybe most sources of proper official documentation get it right these days, but I'm hesitant to assume even that. > Your malloc() example is much better. malloc vs fork failures also have different consequences. malloc failing is pretty unlikely to result in killing other processes (like your watchdog process!) for example. So perhaps it's just as bad of an example ;)