Re: errno/strerror() Observations
From: Paul Pluzhnikov (ppluzhnikov-nsp_at_charter.net)
Date: 04/07/05
- Next message: Kasper Dupont: "Re: Advanced linker magic"
- Previous message: Josh Birnbaum: "Re: errno/strerror() Observations"
- In reply to: Josh Birnbaum: "Re: errno/strerror() Observations"
- Next in thread: Josh Birnbaum: "Re: errno/strerror() Observations"
- Reply: Josh Birnbaum: "Re: errno/strerror() Observations"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 06 Apr 2005 20:20:14 -0700
Josh Birnbaum <engineer@noorg.org> writes:
>> Try commenting it out and see if the problem goes away.
>
> I've done this and I still see the problem.
Well, something resets the errno ...
> This works fine under IRIX but fails under Linux. I'd like to
> find out why.
Hardware watchpoints to the rescue.
On x86, you can set a breakpoint on a memory location, and have
gdb stop when that value changes.
Here is an example:
$ cat junk.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void error(const char *p)
{
fprintf(stderr, "Error in %s: %s\n", p, strerror(errno));
}
int main()
{
const char *fname = "/no/such/file";
FILE *fp = fopen(fname, "r"); // sets errno
if (!fp) {
char *p = malloc(~(0UL)); // resets errno; but pretend we don't know this
error("fopen");
}
return 0;
}
$ gcc -g junk.c && ./a.out
Error in fopen: Cannot allocate memory
So, let's pretend we expected "Error in fopen: No such file or
directory" and got something else instead. Let's find out who
resets errno.
$ gdb -q ./a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x80484ef: file junk.c, line 12.
(gdb) r
Breakpoint 1, main () at junk.c:12
12 const char *fname = "/no/such/file";
(gdb) n
13 FILE *fp = fopen(fname, "r"); // sets errno
(gdb) n
14 if (!fp) {
(gdb) p errno
Cannot access memory at address 0x8
That's not very good. We can't even look at the global "errno"
variable. This is because on Linux errno is actualy #define'd to
(*(__errno_location())).
Let's see what that function returns:
(gdb) p/x __errno_location()
$1 = 0xb7ff2440
(gdb) x/x $1
0xb7ff2440: 0x00000002
This is good: 2 == ENOFILE, which is what we expected.
Let's set a watchpoint and see what code modifies that value:
(gdb) watch *(int *)$1
Hardware watchpoint 2: *(int *) $1
(gdb) c
Hardware watchpoint 2: *(int *) $1
Old value = 2
New value = 12
0x00bc1350 in _int_malloc () from /lib/tls/libc.so.6
(gdb) bt
#0 0x00bc1350 in _int_malloc () from /lib/tls/libc.so.6
#1 0x00bc025d in malloc () from /lib/tls/libc.so.6
#2 0x0804851c in main () at junk.c:15
So now we have the answer -- malloc() reset the errno.
Repeat this for your program, and the mistery should be solved.
Note that gdb will stop on the instruction that *follows* the one
that modified the value (and that instruction may be many lines
distant from the "culprit").
Cheers,
-- In order to understand recursion you must first understand recursion. Remove /-nsp/ for email.
- Next message: Kasper Dupont: "Re: Advanced linker magic"
- Previous message: Josh Birnbaum: "Re: errno/strerror() Observations"
- In reply to: Josh Birnbaum: "Re: errno/strerror() Observations"
- Next in thread: Josh Birnbaum: "Re: errno/strerror() Observations"
- Reply: Josh Birnbaum: "Re: errno/strerror() Observations"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|