This is the mail archive of the gdb@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A simpler, more realistic example of problems with "bt" and C++ exceptions...


I thought I'd "get back to basics" since I'm a bit frustrated with my program,
so I tried something simple:

[george@dhcp34 crack]$ cat > whatthrow.cc
#include <iostream.h>

class What
{
public:
	What() { }
	~What() { }
};

void	throw_what(void)
{
	throw What();
}

int main(int argc, char*argv[])
{
	throw_what();

	return 0;
}

[george@dhcp34 crack]$ g++ whatthrow.cc
[george@dhcp34 crack]$ ./a.out
Aborted
[george@dhcp34 crack]$ gdb a.out
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) run
Starting program: /home/george/crack/a.out

Program received signal SIGABRT, Aborted.
0x400a8d61 in __kill () from /lib/libc.so.6
(gdb) bt
#0  0x400a8d61 in __kill () from /lib/libc.so.6
#1  0x400a8a49 in raise (sig=6) at ../sysdeps/posix/raise.c:27
#2  0x400aa1c0 in abort () at ../sysdeps/generic/abort.c:88
#3  0x40042ef9 in __default_terminate () from
/usr/lib/libstdc++-libc6.1-2.so.3
#4  0x8049908 in __EXCEPTION_TABLE__ ()
#5  0xbffff714 in ?? ()
Cannot access memory at address 0x1
(gdb)

What is wrong here?  Why don't I see main() in the backtrace?  Why don't I see
throw_what() in the backtrace?  What's __EXCEPTION_TABLE__()?  What's
0xbffff714?

Can someone show me exactly what's on the stack at this point?  Have we
unwound past main() or is there crap on the stack between throw_what() and
__default_terminate() that's confusing the debugger?

Here's some more information about the frames:  (recompiled with "-g")

(gdb) l
8       };
9
10      void    throw_what(void)
11      {
12              throw What();
13      }
14
15      int main(int argc, char*argv[])
16      {
17              throw_what();
(gdb) b 12
Breakpoint 1 at 0x8048697: file stupidthrow.cc, line 12.
(gdb) run
Starting program: /home/george/crack/a.out
localhost being added to access control list
dhcp41 being added to access control list
brain being added to access control list

Breakpoint 1, throw_what () at stupidthrow.cc:12
12              throw What();
(gdb) bt
#0  throw_what () at stupidthrow.cc:12
#1  0x8048747 in main (argc=1, argv=0xbffff714) at stupidthrow.cc:17
#2  0x400a29ee in __libc_start_main (main=0x804873c <main>, argc=1,
argv=0xbffff714, init=0x80484d8 <_init>, fini=0x8048810 <_fini>,
rtld_fini=0x4000a570 <_dl_fini>, stack_end=0xbffff70c) at
../sysdeps/generic/libc-start.c:90
(gdb) info frame
Stack level 0, frame at 0xbffff69c:
 eip = 0x8048697 in throw_what(void) (stupidthrow.cc:12); saved eip 0x8048747
 called by frame at 0xbffff6ac
 source language c++.
 Arglist at 0xbffff69c, args:
 Locals at 0xbffff69c, Previous frame's sp is 0x0
 Saved registers:
  ebx at 0xbffff684, ebp at 0xbffff69c, eip at 0xbffff6a0
(gdb) cont
Continuing.

**************
*
*  OK...above we see that the frame is at 0xbffff69c for throw_what().  Stack
grows down on Intel...
*
**************

Program received signal SIGABRT, Aborted.
0x400a8d61 in __kill () from /lib/libc.so.6
(gdb) bt
#0  0x400a8d61 in __kill () from /lib/libc.so.6
#1  0x400a8a49 in raise (sig=6) at ../sysdeps/posix/raise.c:27
#2  0x400aa1c0 in abort () at ../sysdeps/generic/abort.c:88
#3  0x40042ef9 in __default_terminate () from
/usr/lib/libstdc++-libc6.1-2.so.3
#4  0x8049908 in __EXCEPTION_TABLE__ ()
#5  0xbffff714 in ?? ()
Cannot access memory at address 0x1
(gdb) frame 3
#3  0x40042ef9 in __default_terminate () from
/usr/lib/libstdc++-libc6.1-2.so.3
(gdb) info frame
Stack level 3, frame at 0xbffff544:
 eip = 0x40042ef9 in __default_terminate; saved eip 0x8049908
 (FRAMELESS), called by frame at 0xbffff6b4, caller of frame at 0xbffff3bc
 Arglist at 0xbffff544, args:
 Locals at 0xbffff544, Previous frame's sp is 0x0
 Saved registers:
  ebp at 0xbffff544, eip at 0xbffff548

**************
*
*  __default_terminate's frame is 0xbffff544...maybe we haven't unwound after
all...
*
**************

(gdb) bt
#0  0x400a8d61 in __kill () from /lib/libc.so.6
#1  0x400a8a49 in raise (sig=6) at ../sysdeps/posix/raise.c:27
#2  0x400aa1c0 in abort () at ../sysdeps/generic/abort.c:88
#3  0x40042ef9 in __default_terminate () from
/usr/lib/libstdc++-libc6.1-2.so.3
#4  0x8049908 in __EXCEPTION_TABLE__ ()
#5  0xbffff714 in ?? ()
Cannot access memory at address 0x1
(gdb) frame 4
#4  0x8049908 in __EXCEPTION_TABLE__ ()
(gdb) info frame
Stack level 4, frame at 0xbffff6b4:
 eip = 0x8049908 in __EXCEPTION_TABLE__; saved eip 0xbffff714
 (FRAMELESS), called by frame at 0x1, caller of frame at 0xbffff544
 Arglist at 0xbffff6b4, args:
 Locals at 0xbffff6b4, Previous frame's sp is 0x0
 Saved registers:
  ebp at 0xbffff6b4, eip at 0xbffff6b8

**************
*
*  Hmmm...0xbffff6b4...maybe we have unwound...
*
**************

(gdb) frame 5
#5  0xbffff714 in ?? ()
(gdb) info frame
Cannot access memory at address 0x1
(gdb)

**************
*
*  That was weird...try running it again...
*
**************

(gdb) b main
Breakpoint 2 at 0x8048742: file stupidthrow.cc, line 17.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/george/crack/a.out
localhost being added to access control list
dhcp41 being added to access control list
brain being added to access control list

Breakpoint 2, main (argc=1, argv=0xbffff714) at stupidthrow.cc:17
17              throw_what();
(gdb) bt
#0  main (argc=1, argv=0xbffff714) at stupidthrow.cc:17
#1  0x400a29ee in __libc_start_main (main=0x804873c <main>, argc=1,
argv=0xbffff714, init=0x80484d8 <_init>, fini=0x8048810 <_fini>,
rtld_fini=0x4000a570 <_dl_fini>, stack_end=0xbffff70c) at
../sysdeps/generic/libc-start.c:90
(gdb) info frame
Stack level 0, frame at 0xbffff6ac:
 eip = 0x8048742 in main (stupidthrow.cc:17); saved eip 0x400a29ee
 called by frame at 0xbffff6e8
 source language c++.
 Arglist at 0xbffff6ac, args: argc=1, argv=0xbffff714
 Locals at 0xbffff6ac, Previous frame's sp is 0x0
 Saved registers:
  ebp at 0xbffff6ac, eip at 0xbffff6b0
(gdb)




Hmm...main is at 0xbffff6ac...that's deeper in the stack than 0xbffff6b4.  I
guess
we might have unwound after all...Is that what I'm seeing here?  It seems a
little
strange considering that __default_terminate()'s frame is far deeper in the
stack
than the initial invocation of the throw.

The reason I'm so suspicious is that if I do the same sort of thing in my big
C++
program that crashes with ulimit -s 64, that throw_helper is 64k deeper in the
stack
than the initial thread entry point, and the debugger says "Previous frame's
sp is 0x0".

I know all those other frames are there, but the exception handling manages to
structure the stack in such a way that gdb can't read it.  Does that sound
right to you?
--
George T. Talbot
<george at moberg dot com>

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]