I'm a CS student at the Technion, I have just learned of errno
variable and c-style function calls.
This makes me wonder, if c-style syscalls use registers to return a value, why should anyone use errno
at all?
-
2Wasn't `errno` a C stdlib thing instead of having to do anythnig with syscalls and Linux? – Joey May 15 '11 at 08:38
-
@Joey I was thinking the same thing. – Iustin May 15 '11 at 08:42
-
4Errno is a 30-35 year old design decision (or was it older?); trying to understand it now, in the context of today's (vastly more powerful) machines and (vastly more complex and more capable) languages is probably not going to help much. It is what it is. – Fred Nurk May 15 '11 at 09:03
-
2Please do not use unless I give permission! (I have been stared at by many C programmers when introducing myself...) – Emond May 15 '11 at 13:41
-
@Erno: Are you really a 30-35 year old design decision? – Mike Sherrill 'Cat Recall' May 16 '11 at 01:00
-
@Catcall, I am a bit older than that but the design goes waaaay back ;) – Emond May 16 '11 at 04:15
-
@FredNurk FYI the errno is the main source of a messages about an errors on GNU/Linux. Almost everything bad that could occur — network, file system, permission — is returned via errno. And IMAO Windows®'s surrogate «GetLastError()» and «FormatMesage()» versus standard «errno» and «perror()/strerror()» is an overkill. – Hi-Angel Sep 26 '14 at 12:39
4 Answers
The main reason for using errno
is to give more information about the error condition.
This is especially useful in situations where most (or even all) possible return values of a function are actually valid return values.
Consider the fopen()
function, which returns a pointer to a FILE
. Every possible return value is also a valid return value, except NULL
. So fopen()
returns NULL
on failure. But then you can't tell what exactly made the function fail. Hence, fopen()
uses errno
to denote the exact error condition, i.e. the file doesn't exist, or you don't have permission to read it, or the system is out of memory, or whatever.
You can think of errno
as a global variable (which it used to be until threads became popular). Nowadays, errno
is usually a macro wrapping a function call returning the error condition. But this is just C's way of implementing thread-specific global variables.
The alternatives to errno
are less comfortable:
You could supply a function with a pointer to an int
, and the function can store its error condition there. strtod()
is a good example of this technique. But this makes the API more complicated and hence less desirable. Also, it forces the programmer to define a new int
, which is annoying if you don't care if the function fails.
In languages that allow more than one return value (and don't feature exceptions), it's common to return two values: one for the actual result and another to denote the error condition. In languages like Go, you see code like the following:
result, ok = foo();
if (ok) {
// handle error denoted by "ok"
}
Don't trust people who claim that errno
is an "old" technique and hence to be avoided. The machine you're programming is far older than errno
or even C, and nobody has ever complained about that.

- 5,795
- 3
- 33
- 68
-
1Thanks. That was helpful. I still not sure why only sys calls used that variable and not all user-space function – David May 22 '11 at 14:12
-
Actually, a lot of functions from the C standard library use `errno`, e.g. `malloc()` or `fopen()`. Do you know the difference between system calls, *standard* library functions and library functions? – Philip May 22 '11 at 16:07
-
2I question your assertion that nobody has ever complained about C :) – Jeremy Friesner Jan 18 '18 at 02:20
-
2This might be reasonable for some high-level API, but consider Linux syscall warper API, the actual syscall will always return a int through a register, negative values indicate different types of errors and non-negtive values indicate success. Using errno for such interfaces makes a hard-to-use anti-humanity state machine, instead, direct return value would make API closer to real kernel ABI and easier to understand. – 炸鱼薯条德里克 Sep 27 '18 at 16:22
-
Exceptions are not always better than error numbers, especially when the error is supposed to be dealt with by its immediate, that is, the error is actually checked and handled ON THE SPOT. – John Z. Li Oct 24 '18 at 03:12
-
2What about linux APIs, e.g. `int fd = open(...);`? A valid fd is positive so there's plenty of room to convey the error code through a negative value, yet `errno` is still used... – Tomek Sowiński Nov 29 '18 at 08:23
-
@TomekSowiński `errno` for `open(2)` is the result of wrapping of actual Linux-specific system call by glibc to provide POSIX interface of the standard system call. – Ruslan Aug 30 '20 at 16:29
-
@Ruslan ok, so it's posix not linux. Still doesn't explain *why* posix didn't use the negative handle value to convey the error code. – Tomek Sowiński Sep 01 '20 at 10:51
The design of the C library was done a long time ago at the same time as early Unix. Use of a separate error code is not an uncommon pattern (Win32 has the similar GetLastError()). And it has superficial advantages.
If you decide you want a class of functions to have a return value that is commonly used, then you can't easily use that to return errors. For example, imagine a hypothetical API
mytime_t t = get_current_time();
The common use of this API is to get time. But perhaps it can fail in some circumstances, and you get detailed error information from errno. This makes the API code a bit easier to read and write than if you had to say
mytime_t t=0;
errno_t e = get_current_time(&t);
So superficially, errno-type systems are appealing. However, the separation of error state from the actual function call leads to lots of problems. Modern environments make errno_t a per-thread variable (removing the most obvious source of problems), but you still face the problem that if you do
mytime_t t = get_current_time();
mysize_t s = get_window_size();
then you destroy the errno from the first function invisibly. This gets even more complex when code can run in error paths or where one function is implemented in terms of others. Lots of saving and restoring errno values ensures. I think it's pretty well accepted now that such systems are fragile and undesirable.
Many folks use exceptions which carry errors outside the explicit parameter/return set (many C++ programmers make this choice). Folks working in exception-free languages or environments tend to bite the bullet and reserve the return value for an error and always provide output through parameters (COM makes this choice with HRESULTs).

- 11,516
- 10
- 61
- 114

- 2,086
- 11
- 13
-
Though "errno_t e; mytime_t t = get_current_time(&e);" makes a better comparison. – Fred Nurk May 15 '11 at 09:11
errno
is a complicated thing, in that it is an historic interface that probably nowadays nobody would design like that. In addition on most systems it nowadays only looks like a variable, it ain't one. Usually it is implemented as a macro that hides a function call, and that function call returns a thread specific error condition.

- 76,821
- 6
- 102
- 177
-
1Can I use this for my Bio? I am quite complicated... (Sorry couldn't resist ;-) ) – Emond May 15 '11 at 13:43
-
@Erno, no, no, no. First get your spelling corrected, or invent a story why on early unixes you had to use a 5 letter name because of storage restriction or so. You wouldn't get away with it as easy as this. – Jens Gustedt May 15 '11 at 14:23
-
1my spelling software returns an errno when I spell errno because I added erno to the dictionary. Perhaps Erno should cause an errno because it is spelled wrong... – Emond May 15 '11 at 15:45
The best example that I can think of is the stdio function fopen
, which returns NULL at failure and the only way to find out why it failed is through errno and/or perror.
There must be other examples. This is just what sprung in to mind at the moment.

- 143,097
- 13
- 135
- 256

- 1,220
- 1
- 12
- 17
-
Thanks for the rapid answer. What I meant, is why does (for example) fopen uses errno from the first place? – David May 15 '11 at 08:43
-
Alternatively it could have had another parameter to store the possible error. Something like fopen( ... int *err). If you're asking why they chose one method over the other, I can't answer that at the moment. – Iustin May 15 '11 at 08:54