home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: gnu.gdb.bug
- Path: sparky!uunet!cis.ohio-state.edu!cat.rpi.edu!tarbox
- From: tarbox@cat.rpi.edu (Glenn Tarbox)
- Subject: (none)
- Message-ID: <9208211707.AA26966@cat.rpi.edu>
- Sender: gnulists@ai.mit.edu
- Organization: GNUs Not Usenet
- Distribution: gnu
- Date: Fri, 21 Aug 1992 17:07:32 GMT
- Approved: bug-gdb@prep.ai.mit.edu
- Lines: 215
-
- Hello,
-
- This is what I hope is a complete bug report on a problem with gdb
- which I know existed in 4.4 and is still with us in 4.6.
-
- First the necessary background. The computer sytem is a Sun Sparc
- running 4.1.1. I used the gcc-2.2.2 compiler to compile gdb and the
- test program included. When gdb is compiled using suns cc compiler,
- the problem persists.
-
- To compile the test program code included I used the following:
-
- g++ -ggdb3 -o testgdb testgdb.cc
-
- Simply stated, the problem is that (using g++) when passing an object
- by value to a subroutine, the debugger gets the address of the object
- passed into the subroutine wrong. Therefore, when looking at that
- object, it has garbage inside.
-
- The object does get passed correctly, however, as the test code which I
- wrote illustrates.
-
- First, the code which illustrates the problem. The line numbers correspond
- to those provided by gdb. At the end of this note, this file is provided
- without the numbers to facilitate testing at your site.
-
- 1 #include <stdio.h>
- 2
- 3 class mytestclass{
- 4 int first, second, third, fourth;;
- 5 public:
- 6 mytestclass(){first=second=third=fourth=1;}
- 7 mytestclass(mytestclass &inarg);
- 8 void printout();
- 9 };
- 10
- 11 mytestclass::mytestclass(mytestclass &inarg)
- 12 {
- 13 (*this)=inarg;
- 14 fprintf(stderr," in the copy constructor\n");
- 15 printout();
- 16 }
- 17
- 18 void mytestclass::printout()
- 19 {
- 20 fprintf(stderr," variables = %d, %d, %d, %d\n",first,second,third,fourth);
- 21 fprintf(stderr," this = %X\n",(int)this);
- 22 }
- 23
- 24 void testsubroutine(mytestclass subarg);
- 25
- 26 main()
- 27 {
- 28 mytestclass testone;
- 29
- 30 mytestclass testtwo(testone);
- 31
- 32 testsubroutine(testtwo);
- 33 }
- 34
- 35 void testsubroutine(mytestclass subarg)
- 36 {
- 37 fprintf(stderr," in the subroutine\n");
- 38 subarg.printout();
- 39 }
-
- When this code is run, the following output is produced:
-
- in the copy constructor
- variables = 1, 1, 1, 1
- this = F7FFF850
- in the copy constructor
- variables = 1, 1, 1, 1
- this = F7FFF840
- in the subroutine
- variables = 1, 1, 1, 1
- this = F7FFF840
-
- What this code shows is that in the copy constructor, the same object is
- being initialized as is eventually being passed to the testsubroutine
- subroutine. The code works as we expect it would.
-
- But, the issue is: What happens to gdb when looking at an object which
- has been passed by value to a subroutine and when a copy constructor
- is provided? Here is a gdb session which explores that question.
-
- NOTE: I have annotated this session with comments after the gt>
- symbol
-
- Current directory is /home/a/tarbox/testgdb/
- GDB is free software and you are welcome to 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.
- GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
- (gdb) Breakpoint 1 at 0x2320: file testgdb.cc, line 14.
- (gdb) Breakpoint 2 at 0x2404: file testgdb.cc, line 32.
- (gdb) Breakpoint 3 at 0x2454: file testgdb.cc, line 37.
- (gdb) r
- Starting program: /home/a/tarbox/testgdb/testgdb
-
- Breakpoint 1, mytestclass::mytestclass (this=0xf7fff850, inarg=@0xf7fff860)
- at testgdb.cc:14
- (gdb) p this
- $1 = (struct mytestclass *) 0xf7fff850
- (gdb) c
- Continuing.
- in the copy constructor
- variables = 1, 1, 1, 1
- this = F7FFF850
-
- Breakpoint 2, main () at testgdb.cc:32
- (gdb) p &testtwo
- $2 = (struct mytestclass *) 0xf7fff850
- (gdb) p testtwo
- $3 = {first = 1, second = 1, third = 1, fourth = 1}
- (gdb) c
- Continuing.
-
- gt> We see here that the "this" pointer printed by fprintf in the
- gt> copy constructor is the same as what gdb sees for testtwo
- gt> after it is created in main(). This is how we expect the copy
- gt> constructor to work.
-
- Breakpoint 1, mytestclass::mytestclass (this=0xf7fff840, inarg=@0xf7fff850)
- at testgdb.cc:14
- (gdb) p this
- $4 = (struct mytestclass *) 0xf7fff840
- (gdb) c
- Continuing.
- in the copy constructor
- variables = 1, 1, 1, 1
- this = F7FFF840
-
- gt> Here, in the copy constructor, which is being called because the
- gt> argument to testsubroutine is being passed by value, we see that
- gt> "this" as printed by gdb and printed by fprintf correspond.
-
- Breakpoint 3, testsubroutine (subarg={first = 4194437, second = 8292,
- third = 8296, fourth = 0}) at testgdb.cc:37
- (gdb) p &subarg
- $5 = (struct mytestclass *) 0xf7fff7c8
- (gdb) p subarg
- $6 = {first = 4194437, second = 8292, third = 8296, fourth = 0}
- (gdb) c
- Continuing.
- in the subroutine
- variables = 1, 1, 1, 1
- this = F7FFF840
-
- >gt Here is the problem. The address for subarg is different than the
- gt> "this" in the copy constructor which created subarg. However, the
- gt> value F7FFF840 is what gdb had for "this" when in the copy constructor.
- gt> The value for subarg used by gdb, 0xf7fff7c8, is wrong as indicated by
- gt> value printed by fprintf for that object in printout().
-
- Program exited normally.
- (gdb) quit
-
- So, the problem here is simple to state. Somehow, when an object is
- passed to a subroutine by value, and a copy constructor exists, gdb
- evaluates an incorrect address to that object.
-
- Thanks for you time,
-
- -glenn
-
- ------------------------------------------------------------------------
- Glenn Tarbox - tarbox@cat.rpi.edu (518) 276-8367
- New York State Center for Advanced Technology in Automation and Robotics
- CII-8015, Rensselaer Polytechnic Institute, Troy, NY 12180-3590
- ------------------------------------------------------------------------
-
- PS: Below is the program code without the numbers so you can take it
- directly and play with it.
-
- #include <stdio.h>
-
- class mytestclass{
- int first, second, third, fourth;;
- public:
- mytestclass(){first=second=third=fourth=1;}
- mytestclass(mytestclass &inarg);
- void printout();
- };
-
- mytestclass::mytestclass(mytestclass &inarg)
- {
- (*this)=inarg;
- fprintf(stderr," in the copy constructor\n");
- printout();
- }
-
- void mytestclass::printout()
- {
- fprintf(stderr," variables = %d, %d, %d, %d\n",first,second,third,fourth);
- fprintf(stderr," this = %X\n",(int)this);
- }
-
- void testsubroutine(mytestclass subarg);
-
- main()
- {
- mytestclass testone; // create a default object
-
- mytestclass testtwo(testone); // test the copy constructor
-
- testsubroutine(testtwo);
- }
-
- void testsubroutine(mytestclass subarg)
- {
- fprintf(stderr," in the subroutine\n");
- subarg.printout(); // print the object passed by value
- }
-
-