Reputation: 10695
I am looking at the following code in an SO "Low Quality" post to make sure the sample works, and my question is why can't I print errno's value?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(){
FILE *fp;
errno = 0;
fp=fopen("Not_exist.txt","r");
if(fp == NULL && errno == ENOENT)
perror("file not exist");
return 0;
}
Here is what happens when I try to print the value:
(gdb) p errno
Cannot find thread-local variables on this target
(gdb)
I can print fp's value just fine. As you would expect it's value is 0x00
.
I looked at /usr/include/errno.h
and a lot of the other include files included as part of errno.h
, and I cannot figure out how errno is defined. Any pointers or help would be appreciated. I'm just curious about it; nothing is broken.
Thank you.
Upvotes: 21
Views: 20614
Reputation: 263627
errno
is actually required by the C standard to be a macro that expands to a modifiable lvalue. In the simplest case, it can expand to the name of a declared variable, but for implementations that need distinct errno
objects for different threads, it's typically defined something like this:
#define errno (*__errno_location ())
gdb
is usually able to evaluate function calls; for example, on my system:
(gdb) p __errno_location()
$1 = -134383968
(gdb) p errno
Cannot find thread-local variables on this target
The first printed value happens to be the low-order 32 bits of the pointer value returned by __errno_location()
. I don't know gdb well enough to explain that behavior, but it does demonstrate that it can execute function calls.
As a workaround, you can modify the source code so that it saves either the address of errno
, or its value, in a variable that gdb can display:
(gdb) l
1 #include <errno.h>
2 #include <stdio.h>
3 int main(void) {
4 errno = 42; /* arbitrary value */
5 const int *errno_ptr = &errno;
6 int errno_value = errno;
7 printf("%d %d %d\n", errno, errno_value, *errno_ptr);
8 }
(gdb) b 8
Breakpoint 1 at 0x4005b6: file c.c, line 8.
(gdb) r
Starting program: /home/kst/c
42 42 42
Breakpoint 1, main () at c.c:8
8 }
(gdb) p errno
Cannot find thread-local variables on this target
(gdb) p errno_value
$1 = 42
(gdb) p *errno_ptr
$2 = 42
The *errno_ptr
approach has the advantage that you only have to assign it once -- unless you're debugging a multi-threaded program. In that case, the value of &errno
can vary depending on the thread in which you evaluate it.
This is probably a bug, or at least a missing feature, in gdb
.
UPDATE Kevin Cox's comment suggests a workaround:
print *((int*(*)())__errno_location)()
And with gcc 6.2 and gdb 7.11, print errno
actually works:
(gdb) l
1 #include <errno.h>
2 int main(void) {
3 errno = 42;
4 return 0;
5 }
(gdb) b 4
Breakpoint 1 at 0x6bf: file c.c, line 4.
(gdb) r
Starting program: /home/kst/c
Breakpoint 1, main () at c.c:4
4 return 0;
(gdb) p errno
$1 = 42
(gdb)
Upvotes: 7
Reputation: 1189
As others have said, errno
is not a variable that gdb can print. But gdb can
evaluate functions, and __errno_location()
returns a pointer to `errno'. The only thing we need to do then, is to call the function and dereference the restult:
(gdb) p *__errno_location()
And that's it.
Upvotes: 8
Reputation: 47583
In my Ubuntu installation, I have the following section in bits/errno.h
:
/* Function to get address of global `errno' variable. */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ())
# endif
That said, errno
is not necessarily a variable. For various reasons you may want to have a function returning the error value for you rather than a simple extern int
.1 That is why you can't print its value using GDB.
1 of course, as you can see the function call should return the pointer to the actual variable and the errno
macro would dereference it.
Upvotes: 12
Reputation: 19
_CRTIMP int* __cdecl __MINGW_NOTHROW _errno(void);
#define errno (*_errno())
This is used so that, you can just pass the address of a preferred veriable which will contain the actual error value returned from the calling function.
E.g. You can define the function _errno() as below
unsigned int errorValue;
int* _errno()
{
return (&errorValue);
}
Now usage:
void MyFunc()
{
if(some condition failure)
errno = 10; //Or any error value as per your design
else
{
//Actual operation
}
}
After MyFunc()
is executed, errorValue
will contain the error.
Upvotes: 1
Reputation: 994619
The errno
variable is kind of an odd duck. Because most runtime libraries these days support threads, there can't be just one errno
variable. If there were, then two threads could do things at the same time that both set the errno
value, and great confusion would ensue.
Runtime libraries do various tricks to avoid this problem. For example, one might do something like:
#define errno __get_errno()
where references to errno
actually call the internal __get_errno()
function, which returns the correct error number value for the current thread. The disadvantage of this method is it prevents assignment to errno, such as errno = 0;
(which some code might do). Runtime libraries will usually choose a more sophisticated approach.
Some runtime libraries (like the one you're using, I suppose) can declare a special type of "thread-local variable" which can have a different value on each thread. It sounds like your debugger on your system can't display that kind of variable.
Upvotes: 14