Re: How to call operator<< functions?

Michael Veksler
2006-08-30T20:05:52Z

Daniel Jacobowitz wrote:
> As a general note: the most useful thing to accompany any bug report is
> a test case! :-) We can't fix them without tests.
>
You are right. At the end of this mail there is a complete test case for
about 50% of the reported problems. I'll have to work harder for a
simple test case for the other 50%.
> On Wed, Aug 30, 2006 at 01:11:43PM +0300, Michael Veksler wrote:
>
>> I wanted to do the same for operator<<:
>> (gdb) p 'operator<<(std::ostream&, MyClass const&)'
>> $17 = {ostream &(ostream &, const class MyClass
>> &)} 0x8068a00 <operator<<(std::ostream&, MyClass const&)>
>> (gdb) p $17(gecLog, *pd)
>> Program received signal SIGSEGV, Segmentation fault.
>>
> You can just use "print gecLog << *pd". Does that work better?
> Anyway, I would have expected calling the operator to work.
>
>
Does not work, look at my complete report below.
> With tests for these bugs we can make the next GDB release the
> best ever for C++.
>
Would be great.
>> Print(cerr). Sometimes, while debugging a piece of code, that a vital
>> object has <<, but no DebugPrint, and *that* really frustrates me -
>> especially when I loose a 60 minutes debugging session to a SIGSEGV.
>>
>
> You might want to use set unwindonsignal, then, as it suggests.
> There's some risk associated, but it usually works. You can also
> use "return" to get out of the called function, but make sure you tell
> GDB not to pass the sigsegv when you continue.
>
>
Thanks this might help 95% of the time.
In some cases I get std::bad_alloc uncaught exception during Print
(again, when it should have worked). I doubt that these 5% of crashes
can be recovered from. Not a big deal, as it is only about 5..10%.

The complete test case is comprised of c++ source file (compiled with
RHEL4's gcc-3.4 using "g++ -g "), and of screen trace.

Should I open a PR, or several PRs?
Maybe someone else that can split my single test case into subtopics,
each to fit its own PR?
Does it make sense to create test case for the missing 50% of the
crashes I have seen, or will it be better to wait and see if they get
fixed by other PRs?
===================
=> cat cout-gdb.cpp
#include <iostream>

using namespace std;
ostream myCout(cout.rdbuf());

struct A
{
virtual void Print(ostream &out) const = 0;
};

struct B : public A
{
virtual void Print(ostream &out) const
{ out << "Enter B::Print() this=" << this << endl; }
};

ostream & operator<<(ostream & out, const A& data)
{
data.Print(out);
}
int main()
{
B x;
const A & ref_x = x;
ref_x.Print(myCout);

return 0;
}
=> gdb-6.5 -silent a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b 27
Breakpoint 1 at 0x8048a26: file cout-gdb.cpp, line 27.
(gdb) r
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00

Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p x.Print(myCout)

Program received signal SIGSEGV, Segmentation fault.
0x0042cf88 in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function
(B::Print(std::ostream&) const) will be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00

Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p ref_x.Print(myCout)

Program received signal SIGSEGV, Segmentation fault.
0x0042cf88 in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function
(B::Print(std::ostream&) const) will be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00

Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p ref_x.Print
Cannot take address of method Print.
(gdb) p x.Print
$1 = &B::Print(std::ostream&) const
(gdb) p $1(&x, myCout)
Enter B::Print() this=0xbfffec00
$2 = void
(gdb) set $a=x.Print
(gdb) p $a(&x, myCout)

Program received signal SIGSEGV, Segmentation fault.
0x08527e78 in ?? ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (at 0x8527e78) will
be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00

Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p myCout << x
Structure has no component named operator<<.
(gdb) p 'operator<<(std::ostream&, A const&)' (myCout, x)
Enter B::Print() this=0xbfffec00
$3 = (ostream &) @0x8049260: <incomplete type>
<<<<<< The above sometimes won't work (will be reproduced later) >>>>
(gdb) p &'_ZSt4cout@@GLIBCXX_3.4'
$4 = ( *) 0x8049160
(gdb) p &std::cout
$5 = (ostream *) 0x47cfc0
(gdb) p x.Print
$6 = &B::Print(std::ostream&) const
(gdb) p $6(&x, '_ZSt4cout@@GLIBCXX_3.4')
Enter B::Print() this=0xbfffec00
$7 = void
(gdb) p $6(&x, std::cout)

Program received signal SIGSEGV, Segmentation fault.