Reputation: 27210
In usual case open()
return the new file descriptor, or -1 if an error occurred and in that case, errno
is set appropriately.
I am not understanding why this mechanism of errno
is used here? whats the purpose of here? why just we can not map all error with some negative return no?
like
fd = open("/dev/tty0", O_RDWR | O_SYNC);
if(fd == -1)
printf("this is EACCES error");
else if (fd == -2)
printf("this is EPERM error");
Is there any benifit of errno
mechanism.? if yes then i would like to know/understand then in other things i can also use this mechanism.
Upvotes: 8
Views: 3136
Reputation: 78903
Since fopen
returns a FILE*
you can't expect it to return an error code in that pointer: the only "special" value for pointers is 0
.
As you observe, for open
this restriction doesn't hold. In fact systems as linux do exactly what you propose in their lower levels. The system call under the hood returns the negative error code if things go wrong. That (negated) code is then plug into errno
by a shallow user space wrapper which then returns the -1
to indicate the error to the application.
The reason that this is done so is purely historical. In good old times there was no threading and errno
was still just a simple global variable. At that time the chosen strategy incurred not much overhead and probably seemed an acceptable way to communicate between OS and application. Since such interfaces basically can't be changed without breaking a lot of code, we will be stuck with errno
as a pseudo variable that is thread local.
This is not ideal, but the overhead is not as bad as it sounds, since these are clearly error indications that should occur only exceptionally.
Upvotes: 12
Reputation: 477040
Giving each function a distinct set of return values makes it overly complicated to write code in a generic fashion. With the current semantics, you can adopt a universal pattern:
int fd;
if ((fd = some_function(arg1, arg2)) == -1)
{
perror("some_function");
exit(1);
}
You can even wrap this in a macro:
#define CALL_OR_DIE(function, ret, ...) \
if ((ret = function(__VA_ARGS__)) == -1) \
{ perror(#function); exit(1); }
Usage:
int fd;
CALL_OR_DIE(open, fd, "/dev/tty0", O_RDWR | O_SYNC);
Upvotes: 1
Reputation: 32953
For me the advantage is that getting the error information is unified in that way, returning some negative value would work OK with open
as it returns an integer, but fopen
returns a FILE *
so another technique would have to be used there.
Upvotes: 9
Reputation:
errno
is an error code. It is important to map the errors to what is actually happening so you can make strategic decisions in your code on what to do next. For instance, ERANGE
which is defined in errno.h
, will tell you that the result of strtol("0xfffffffff",NULL,0)
is out of that function's range. More importantly in your example, it is good to know whether you have an EACCES
or EPERM
error so you know how to handle the file.
You can't map all problems with one error code since you could have multiple issues that you would like to catch and handle. When I say catch, I do not mean try/catch.
The use of errno establishes and error handling mechanism so you get more information than just -1.
ERANGE, EACCES, EPERM, and others are considered macros that map to a particular error number for convenience purposes.
Upvotes: 1