[Converted from Gnats 2065] gdb fails to resolve the address of class constructors correctly if the class declaration (instead of its definition) is found first in the symbol file. Release: 6.4 Environment: i686-pc-linux-gnu How-To-Repeat: If a source file contains a forward declaration of a class, and this file is compiled first, then g++ inserts a "typedef" symbol into the debugging output. If now a breakpoint is set at the constructor of this class, this typedef is resolved instead of the full name, giving it an address of zero. If gdb is requested to list the constructor, it crashes with a segfault. Similarly, if a breakpoint is inserted at the constructor, setting the breakpoint fails because it is thought of to be at address zero. Thus, this bug is hard to reproduce because it depends on the layout of the object file whether the mentioned problem appears. See the fix below, though.
Fix: Replace gdb/symtab.c, lines 1789ff by the following: if (SYMBOL_DOMAIN (sym) == domain && (linkage_name != NULL ? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1)) { /* FIX THOR */ if (domain != VAR_DOMAIN || sym->aclass != LOC_TYPEDEF) /* Must *NOT* use type forwards here */ return sym; } /* FIX THOR end */ This adds an additional test for forward declarations and avoids to return them as valid symbol resolutions.
I tried to reproduce this but couldn't. I tried compiling two files like so: == main.cc class K; extern K *getk(); int main () { K* k = getk(); return 0; } == k.ccclass K { public: K (); int z; }; K::K () { z = 25; } K *getk() { return new K; } I figured this was most likely to get the forward declaration read in first. On trunk I get weird behavior, e.g., "break K::K" does nothing at all. This doesn't sound like your bug, though. Maybe the crash has been fixed. It would be most helpful if you had a simple way to reproduce this.
(In reply to comment #2) > I tried to reproduce this but couldn't. > I tried compiling two files like so: > > == main.cc > class K; > > extern K *getk(); > > int main () { > K* k = getk(); > > return 0; > } > > == k.ccclass K { > public: > K (); > > int z; > }; > > K::K () { > z = 25; > } > > K *getk() { > return new K; > } > > > I figured this was most likely to get the forward declaration read in > first. > > On trunk I get weird behavior, e.g., "break K::K" does nothing at all. > This doesn't sound like your bug, though. Maybe the crash has been fixed. > > It would be most helpful if you had a simple way to reproduce this. What you see here is indeed another bug related to constructors, however, one that isn't fixed by the code above. With the present gdb, I cannot reproduce the 2006 bug anymore, but I can reproduce here (and on my own sources) that setting a breakpoint in a constructor does not work, as you did above. Suggestion: Close the old bug, open a new concerning setting breakpoints on constructors.
Hmmm, the bug the OP has described look very much like PR10966 and PR8166 to me. Notice the last command on: http://sourceware.org/ml/gdb/2010-02/msg00090.html " (gdb) p Foo::Foo Cannot look up value of a typedef " His pseudo-patch doesn't have context to know better, so I can't tell if its essentially the same as the FUNCTIONS_DOMAIN suggestion on PR10966, or a better fix (it may well be, I may very well misdiagnosed the real issue, as I didn't bother with it, given that getting rid of physname gets rid of the bug).
Played again with it. The trouble becomes at least more obvious if the class in question has multiple constructors. Here's how to reproduce - and while gdb certainly doesn't crash anymore, it still tries to set the breakpoint at address 0x0: Enter the following as class.cpp: /* snip */ class A { int x; bool b; A *p; public: A(int i) : x(i), b(false), p(0) { }; A(int i,bool a) : x(i), b(a), p(0) { }; A(int i,A *next) : x(i), p(next) { } ~A() { if (p) p->inc(); } void inc() { x++; } }; A *getA(int x) { A a(1); return new A(x,&a); } void dispose(A *a) { delete a; } /* snip */ Enter the following as main.cpp: /* snip */ extern class A *getA(int x); extern void dispose(class A *); int main(int argc,char **argv) { class A *ap = getA(1); dispose(ap); } /* snip */ Compile with: g++ -c -ggdb3 -O0 -o class.o class.cpp g++ -c -ggdb3 -O0 -o main.o main.cpp Link with: g++ -o a.out class.o main.o Run the debugger with: gdb a.out Then try: break A::A The result of which is: [0] cancel [1] all ?HERE ?HERE ?HERE Then enter 1. The result is: Note: breakpoint -1 (disabled) also set at pc 0x0. Breakpoint 1 at 0x0 Note: breakpoints -1 (disabled) and 1 also set at pc 0x0. Breakpoint 2 at 0x0 Note: breakpoints -1 (disabled), 1 and 2 also set at pc 0x0. Breakpoint 3 at 0x0 warning: Multiple breakpoints were set. Use the "delete" command to delete unwanted breakpoints. Also known as "nonsense". With the patch in question, the situation does in so far get better as errors are no longer printed, but the breakpoint nevertheless doesn't work - or is set at the wrong place. Part of the problem might be that g++ generates multiple routines for the same constructor (i.e. one constructor is expanded into several assembly routines depending on whether the object is allocated on the heap or the stack), and apparently, gdb sets the breakpoint at the wrong place. Unfortunately, this is indeed a long standing bug, I've never been able to debug constructors successfully with any gdb version I have seen so far. The onyl workaround I know is to add a dummy function to constructors and set a breakpoint in this dummy.... So long, Thomas
Yeah, that behavior is what is seen in those other PRs. We do have a patch for this bug, but it won't go in until after 7.1. The patch will go in pretty soon after 7.1 branches, so sometime very soon you should be able to use CVS gdb to solve this.
I believe this is fixed in cvs now.