1+++ 2title = "errno" 3description = "errno with their good and bad sides." 4weight = 20 5+++ 6 7 8The idiom of returning, upon failure, a special value and storing an error code 9(an `int`) inside a global (or thread-local) object `errno` is inherited from C, 10and used in its Standard Library: 11 12```c++ 13int readValue(const char * filename) 14{ 15 FILE* f = fopen(filename, "r"); 16 if (f == NULL) 17 return 0; // special value indicating failure 18 // keep errno value set by fopen() 19 20 int i; 21 int r = fscanf(f, "%d", &i); 22 if (r == 0 || r == EOF) { // special values: i not read 23 errno = ENODATA; // choose error value to return 24 return 0; 25 26 fclose(f); 27 errno = 0; // clear error info (success) 28 return i; 29} 30``` 31 32One advantage (to some, and a disadvantage to others) of this technique is that it 33uses familiar control statements (`if` and `return`) to indicate all execution 34paths that handle failures. When we read this code we know when and under what 35conditions it can exit without producing the expected result. 36 37 38### Downsides 39 40 41Because on failure, as well as success, we write into a global (or thread-local) 42object, our functions are not *pure*: they have *side effects*. This means many 43useful compiler optimizations (like common subexpression elimination) cannot be 44applied. This shows that it is not only C++ that chooses suboptimal solutions 45for reporting failures. 46 47Whatever type we return, we always need a special value to spare, which is 48sometimes troublesome. In the above example, if the successfully read value of 49`i` is `0`, and we return it, our callers will think it is a failure even though 50it is not. 51 52Error propagation using `if` statements and early `return`s is manual. We can easily 53forget to check for the failure, and incorrectly let the subsequent operations 54execute, potentially causing damage to the program state. 55 56Upon nearly each function call layer we may have to change error code value 57so that it reflects the error condition adequate to the current layer. If we 58do so, the original error code is gone. 59