23

In one of my University Projects, I got points off and feedback from my professor saying I didn't handle printf errors.

In English --> / * ### FB: Error handling printf () is missing * /    

/* ### FB: Fehlerbehandlung printf() fehlt */
    printf("%7lu %8lld %10s %3lu %-8s %-8s %8lu %12s  %s %s %s\n",
           sb->st_ino, nblks, permstr, (unsigned long) sb->st_nlink,
           username, groupname, sb->st_size,
           ntime, filename, (symlink ? "->" : ""),
           (symlink ? symlink : "")
           );

My question is, is it really important to always check return value of the printf function and handle the errors? Even if I find an error I will still use fprintf to print to stderr, for which I have to check the return type for fprintf again.

So when should the return value be checked, and how should it be handled?

Seek Addo
  • 1,871
  • 2
  • 18
  • 30
  • Ask your teacher why he considers it important. I have never seen any production code checking the return value and never used it myself. And how exactly are you supposed to handle it anyway? What Paul R. said. ;) – Devolus Mar 21 '17 at 14:19
  • 1
    the first answer to this may be useful http://stackoverflow.com/questions/13535557/why-does-printf-return-a-value –  Mar 21 '17 at 14:20
  • only if you care to know if and how many characters were written :) – Rob Mar 21 '17 at 14:20
  • 9
    *Always* check `scanf`, but I will confess to never checking `printf`. – Bathsheba Mar 21 '17 at 14:21
  • It is opinion based. But for me, as long you only ask about `pintf` (i.e. not `fprintf`, etc.), the worst which can happen is you will mess up the output. Unless your code is intended to be used with output redirection, it is not ideomatic to check for errors. And even for redirection, one would at most check the last call, as anything else will bloat code massively (C does not support exceptions). – too honest for this site Mar 21 '17 at 14:21
  • @Orangesandlemons, that linked to answer doesn't really convince me either. – Devolus Mar 21 '17 at 14:22
  • Evidently, it is important *to your professor* that you handle errors reported by `printf()`. I presume he is prepared to point you to some course policy or assignment-specific instructions that require you to catch and handle either those errors specifically, or, more likely, all errors. – John Bollinger Mar 21 '17 at 14:22
  • @PaulR i was surprise to see it, because it doesn't make sense. – Seek Addo Mar 21 '17 at 14:25
  • Whether it makes sense to do so in a more general context depends on the nature of the program, the reason for the particular `printf()` call, and what you would do to handle such an error if one occurred. I rarely check the return value of `printf()` specifically for the purpose of detecting errors, but occasionally I check it for the purpose of using its success-case return value. – John Bollinger Mar 21 '17 at 14:26
  • If the output is later meant to be used (should be true for `stdout` but not for `stderr` -- if you use them conventionally), then it is important. You don't want to report success if some important info might be missing in your output. – Petr Skocik Mar 21 '17 at 14:26
  • 6
    @SeekAddo: I would guess that your professor has probably not had any experience in writing C professionally, so his opinion on error checking is probably just theoretical/pedantic. – Paul R Mar 21 '17 at 14:27
  • @PaulR i agree with you – Seek Addo Mar 21 '17 at 14:29
  • I'm sure one can contrive situations where printing is critical, and there is "something you can do" that doesn't involve printing to cope with that, or alert someone to the fact, but they are few and far between. I'd go with @PaulR unless specifically explained in the question why it's necessary (and what you should do if it does fail). Even a blanket "check return codes" wouldn't include this situation for most people. – TripeHound Mar 21 '17 at 14:29
  • @JohnBollinger what will you use then to report the errors, fprintf to stderr or printf, in either way then you still have to check the return value again if the error was actually reported. – Seek Addo Mar 21 '17 at 14:30
  • 2
    @SeekAddo, as I said, it depends on what you would do to handle such errors. More likely than not, if you're in a situation where it makes sense to check at all, then the handling would include terminating the thread or process in which the error occurs. Personally, I would precede that with a message to `stderr`, but *that* is a circumstance where it absolutely makes no sense to check the return value (of `fprintf()` / `fputs()`). – John Bollinger Mar 21 '17 at 14:34
  • @JohnBollinger it makes sense thanks for your contribution – Seek Addo Mar 21 '17 at 14:37
  • @SeekAddo Almost nobody checks `printf` errors because there isn't much you can do to handle them. So your professor is just pedantically wrong. That being said, he's still teaching you a valuable lesson. In professional programming you will often be working for idiots with stupid requirements and the lesson you need to learn is if it's worth your time, effort and nerves to argue that you're right or if you just meet the stupid requirement, put some kind of subtle "you're an idiot" in your submission (as a consultant this can be done with an invoice) and move on with your life. – Art Mar 21 '17 at 14:57
  • @Art ahahahah thanks – Seek Addo Mar 21 '17 at 15:00
  • 1
    Checking for an error code from `printf()` is rarely done, so a feedback of "didn't handle printf errors" lacks detail. I suggest, rather than ask SO, constructively ask the professor for details as to why this is important. Understanding customer concerns is the key. – chux - Reinstate Monica Mar 21 '17 at 15:02
  • So if you write `printf("%d\n", i);` does your prof expect you to do an independent calculation of how many characters will be printed for the current value of `i` - including processing the current locale correctly, of course - just to check the error code? Actually, given the quality of too many computer science/engineering graduates looking for jobs, don't answer that - maybe those graduates spent a few years being *taught* to be incompetent ;) – alephzero Mar 21 '17 at 16:17
  • 1
    What are examples of handling printf errors from your professor? – iheanyi Mar 21 '17 at 19:44
  • @iheanyi i have only the feedback without examples or any specific details, I will have to ask him on (System Programming) coming monday. – Seek Addo Mar 21 '17 at 21:03
  • 3
    I don't agree that this is opinion-based. It is fairly clear that checking the result of printf doesn't give you anything meaningful to act on. The only thing that is opinion-based is whether or not you should insist on checking it anyway, for the sake of consistent coding style or to avoid warnings. But that wasn't the question here. Vote to re-open. – Lundin Mar 22 '17 at 07:42
  • What I would like to consider are 2 things not covered before: 1. Was it told you before the exam to use the check in the lessons or not? If it was told you to do so and you didn't do it in the exam is very different than you did it in the exam and didn't knew it would be considered as wrong. - ... – RobertS supports Monica Cellio Jun 20 '20 at 15:59
  • ... 2. What is the specific context of the call? Why do you bring **11** format directives into one call to `printf()`? Without header one will not know what belongs to which output either. Checking the return value of this particular `printf()` call *can* make way more sense than at a "usual" printf() call. – RobertS supports Monica Cellio Jun 20 '20 at 16:00

6 Answers6

18

Generally speaking, you should always check the return value of a function for errors.

In the case of printf however, there is little use in doing so in most cases. As you mentioned, if it does fail you could use fprintf to print to stderr, but then that raises the question of should that be checked for error.

If you don't redirect or reopen stderr you'll likely have the same issue, in which case it probably doesn't matter, but if stderr is pointing someplace else then writing there could have value. You could also exit the process but you need to determine if it makes sense to do so.

One notable time you might want to check the return value is if you want to keep track of how many characters you printed for formatting purposes. I've done this with fprintf when writing to a log file to determine when to roll the log, but since printf generally writes to an interactive console (and if it's not due to redirection, you wouldn't know it), that wouldn't really apply.

As for your professor, my only guess is that he wants you to get into the habit of checking for errors. That is a Good Thing, however like most rules there are exceptions, and this is one of them.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 9
    What can you do if `printf()` fails? You can abort the thread or process, and it may make sense to do so under some circumstances. There are other possibilities. Moreover, if you choose to emit an error message, which is not necessarily a bad idea, the appropriate stream for that is `stderr`, and there's no reason to assume that just because `printf()` (to `stdout`) fails, `fprintf(stderr, ...)` will be ineffective. – John Bollinger Mar 21 '17 at 14:38
  • @JohnBollinger But, unless such situations are specified as part of the question/task, it's probably unreasonable to expect a "university project" to take account of the possibility of `printf` failing. – TripeHound Mar 21 '17 at 14:52
  • 3
    @TripeHound, on the contrary, if applicable instructions call for *all* errors to be recognized and handled, then I see no justification for excluding those produced by `printf()`. Moreover, I see some pedantic value in enforcing such a constraint strictly, not because of the details `printf` in particular, but because of the general importance of understanding how to conform to a specification in detail. Also somewhat to foster an appreciation of the fact that computers don't make the kind of value judgment that suggests making an exception for `printf()`. – John Bollinger Mar 21 '17 at 15:08
  • @JohnBollinger You make some good points about possible actions. I've added those to my answer. – dbush Mar 21 '17 at 15:22
  • 10
    @JohnBollinger The fact that the printf family of functions has horrible error checking, being variable-argument list abominations, makes this discussion pretty pointless. It's like arguing about why someone didn't clean the feet of their elephant before they brought it into your porcelain store. `printf` code using incorrect format specifiers or wrong arguments etc will just violently explode in many forms of UB. It will not return gracefully. Plus it is not necessarily guaranteed to be re-entrant. The proper solution is to avoid `stdio.h` entirely, rather than trying to polish crap. – Lundin Mar 21 '17 at 15:40
  • 2
    @Lundin a decent compiler will check the varadic arguments at compile time is the format string is known (and when is it not?), so that kind of UB should never occur if you compile with -Wall -Werror – k_g Mar 21 '17 at 20:28
  • @k_g This is something gcc started doing fairly late and most other compilers don't. Simply because the compiler isn't required to do it. And you shouldn't rely on it. For example gcc will merrily compile any kind of nonsense if you pass the format string as parameter: `const char* str = "%q%"; printf(str,0,0,0);`. (And no, printf didn't return -1 there either) The solution is to avoid the whole dysfunctional stdio.h library in the first place. – Lundin Mar 22 '17 at 07:35
  • @Lundin what's a portable alternative? – k_g Mar 22 '17 at 23:24
  • @k_g Whatever GUI library that makes sense for your applications. No professionals write console programs today. Nowadays, the console is just some quick & dirty crap used for debugging and test purposes only. – Lundin Mar 23 '17 at 07:27
  • @Lundin by that standard, you should be doing the entire project in c++, I'm not sure who uses c for gui apps anymore – k_g Mar 23 '17 at 07:43
  • 1
    @k_g All mainstream OS are written in C, as is their API:s. Of course hacking GUI in C or C++ is somewhat painful. You'd use Java or C# for the GUI and C for back end stuff, if needed. – Lundin Mar 23 '17 at 08:34
  • @Lundin I really like your original quote, but I completely disagree about professionals writing console apps. Most compilers, assemblers, linkers are mission-critical console applications. What would you suggest they use if not stdio for writing to the console? – ajxs Jul 20 '19 at 06:40
13

For clarity - printf() returns ...

The printf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred. C11 §7.21.6.3 3


Checking the return value of printf() for a negative value is pedantic, and is not usually needed. One could consider the following cases:


Environmental limits.

A single printf() with "%s" may exceed an environmental limit and cause printf() to return a negative value. This would not imply the a subsequent message on fprintf(stderr, ... must also fail.

The number of characters that can be produced by any single conversion shall be at least 4095. C11 §7.21.6.1 15


Weak output devices.

A case where stdout is known to be often re-directed over a communication interface where output failures need to be detected. Even though a screen output has extraordinary high success, this is not so with various others output streams like serial (rs232). In this case stdout and stderr may re-direct differently and so stderr may remain reliable.


In any case, if the professor grades on a curve, likely many incurred the same minus point - so no grade difference. Get use to customers with odd requirements and expectations.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 4
    Most of the time when stdout is a serial port you will get a SIGHUP on disconnect. In order for that to translate to an EIO error from printf, you would need to explicitly ignore the SIGHUP; the default action is to terminate the process and in an application where some other action is appropriate, it would be normal to install a signal handler. A similar observation applies to SIGPIPE, the other likely stdout failure cause. – rici Mar 21 '17 at 16:20
  • 2
    `+(int)(M_PI/3)` for the last sentence. Nail on the coffin. –  Mar 21 '17 at 18:33
  • 1
    FWIW, I experimented with gcc printing a pairs of 2,000,000,000 character strings (+ \0) with `int n = printf("%s %s\n", buf, buf);` and the result was the expected text and the negative return value of `-294,967,294` or `4,000,000,002 - (UINT_MAX + 1))` - so not much of an error indicator on that platform. – chux - Reinstate Monica Mar 21 '17 at 20:00
3

Not checking a return value is considered bad practice. BUT it is considered clean, if you explicitly state that you ignore the return value by adding (void) in front of the function call:

(void) printf(...);

This indicates, that you know there is return value, but you are intentionally ignoring it.

arminb
  • 2,036
  • 3
  • 24
  • 43
  • 2
    No. Casting a return value to `void` as an indication that you are intentionally ignoring it is a mechanism for suppressing diagnostics. It is ugly, verbose, and potentially confusing. It is also decidedly *un*clean, because it hides the issue instead of fixing it. – John Bollinger Mar 21 '17 at 15:14
  • 6
    @JohnBollinger Compared with _not_ casting the result, which means "I had forgotten that this function returns anything and potentially there's a bug in my code because of it". How exactly is that cleaner? An explicit cast means "I know that this function returns something but I don't care". In the case of printf, it will probably not return anything meaningful whatsoever. If it wasn't such a horrible function, it would return errors upon incorrect format string etc, but I have never seen an implementation actually doing that. – Lundin Mar 21 '17 at 15:30
  • @Lundin, if you're sufficiently mindful of the issue in the first place to consider casting to `void`, then it's cleaner to simply *comment* about the fact that you are knowingly ignoring the return value. That furthermore gives you the opportunity to say something about why you're ignoring it. – John Bollinger Mar 21 '17 at 15:51
  • 3
    @JohnBollinger A `(void)` informs the compilation that the result is ignored. A comment would not do that, even if it is cleaner and useful info for a programmer. Some compilers provide the notice about unused return values. A `(void)` silences that instance of the notice. – chux - Reinstate Monica Mar 21 '17 at 18:58
  • Just so, @chux. As I've said from the beginning, my position is that casting to `void` for the purpose of suppressing diagnostics is unclean. A compiler configured to warn about unhandled return values should be allowed and expected to do so. Whoever *builds* the code -- who is not necessarily the person who wrote it -- should be afforded the opportunity to determine whether ignoring the return values is a reasonable choice. – John Bollinger Mar 21 '17 at 19:26
  • 1
    @JohnBollinger Interesting coding model. Does the builder then edit the code with `(void)` if determined ignoring the return values was a reasonable choice, ignores select diagnostics (which could be 100s to 1000s of them), blanket turns-off the warning, goes back to the writer who then edits in a `(void)` or what? My model is one where code that passes code review no longer generates diagnostics. If such a pedantic diagnostic was required, then many `(void)` would exist and the diagnostic would not keep popping up on next builds. – chux - Reinstate Monica Mar 21 '17 at 20:23
2

The Unix philosophy is that stdout (though not necessarily stderr) should be further processable. Compilers and generators use it for code output. stdout should be where your process's product goes. If that product is cut short, your processes shouldn't be returning EXIT_SUCCESS. I say do check those writes to stdout.

(stderr, on the other hand, is more or less for convenience. If you're using it, you're probably in a state of error already anyway, and if your error reporting fails, there's not much you can do (though you should still signal the error with return codes).)

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • @Dmitri In that circumstance, `printf` can fail from `EINTR`s if the writer catches any signals. Otherwise, it shouln't fail, AFAIK (provided the OS and the reader are OK). If you do IPC using regular files as intermediaries (`>` rediction), IO errors are a possibility. – Petr Skocik Mar 21 '17 at 15:31
0

No. In the real world, as opposed to an academic exercise in a culture mit einem Ruf für Pedanterie, it's not important to check the return value of printf(), or close(), or quite a few other things. If there's no reasonable way to act on a piece of information, why bother collecting it?

Community
  • 1
  • 1
Camille Goudeseune
  • 2,934
  • 2
  • 35
  • 56
  • 1
    Djb is pedantic. But I agree with him that it is very good practice to check printf return value https://news.ycombinator.com/item?id=9155741 – yota Dec 10 '17 at 12:49
0

If you are writing an app that spits JSON (for example: read from DB export the data into stdout) the caller of your program might redirect the output into a file. In such case - the disk might get filled.

Question: who will complain about the disk being full: the shell or your program?

elcuco
  • 8,948
  • 9
  • 47
  • 69