Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > try object out of scope before catch?

Reply
Thread Tools

try object out of scope before catch?

 
 
Jackson A. Marshall
Guest
Posts: n/a
 
      01-11-2005
I have a been testing the try/catch exception mechanism
(as implemented by DigitalMars) and found that if I
throw an object its dtor gets called 3 times, if I throw
a reference its dtor gets called twice - and so it seems
practical to instantiate an object and throw its address,
and sure enough, its dtor gets called only once.

This is part of the Test class implementation (contains only
one data member: "int n" ):

volatile int count = 0;

// Constructor
Test::Test() : n(0) {
++::count;
std::cout << " Test(" << ::count << ")\n";
}

// Constructor
Test::Test(int nn) : n(nn) {
++::count;
std::cout << " Test(" << ::count << ")\n";
}

// Destructor
Test::~Test() {
std::cout << "~Test(" << ::count << ")\n";
--::count;
}

// e.g. Test1 += Test2;
const Test& Test:perator+=(const Test& rhs) {
std::cout << "operator+=(Test&)\n";
if(this == &rhs) {
Except ex("operator+= self assignment!");
throw( &ex );
}
n += rhs.n;
return *this;
}

The Except class implementation..

volatile int except = 0;

// Constructor
Except::Except(const char* msg = 0) : data(msg) {
++::except;
std::cout << " Except(" << ::except << ")\n";
}

// Destructor
Except::~Except() {
std::cout << "~Except(" << ::except << ")\n";
--::except;
}

// access data
const char* Except::Get() { return data; }


int main() {
Test t;
try { t += t; }
catch( Except* e ) {
cout << "Throw() caught: " << e->Get() << "\n";
return -1;
}
}

Output:
======
Test(1)
operator+=(Test&)
Except(1)
~Except(1)
Throw() caught: operator+= self assignment!
~Test(1)

But this implies that Except goes out of scope before
the throw is caught. I would have liked to have seen:

Test(1)
operator+=(Test&)
Except(1)
Throw() caught: operator+= self assignment!
~Except(1)
~Test(1)

Anyone comments?

TIA
>jam

--
"Capitalism is the extraordinary belief that the
nastiest of men, for the nastiest of reasons, will
somehow work for the benefit of us all."
[John Maynard Keynes]




 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      01-11-2005
Jackson A. Marshall wrote:
> I have a been testing the try/catch exception mechanism
> (as implemented by DigitalMars) and found that if I
> throw an object its dtor gets called 3 times, if I throw
> a reference its dtor gets called twice - and so it seems
> practical to instantiate an object and throw its address,
> and sure enough, its dtor gets called only once.
>
> This is part of the Test class implementation (contains only
> one data member: "int n" ):
>

[...]
>
> Anyone comments?


Here is a comment: regarding your code and the sequence of d-tors,
you're throwing an address of a local variable. It gets destroyed
before you catch it. When you after catching the value of the
pointer attempt to use it, you get undefined behavour.

And also your 'Test' class doesn't seem to have any copy c-tor
implemented, thus making it impossible for you to track copy
construction (not that you should expect any, but still).

If you want to throw by an address (pointer), you have to use
either a global object (that survives the stack unwinding) or
a dynamic object (use 'new'). Of course, it's better to throw
a temporary object and catch by a const reference.

V
 
Reply With Quote
 
 
 
 
Jackson A. Marshall
Guest
Posts: n/a
 
      01-11-2005
"Victor Bazarov" <> wrote in message news:F8REd.35036$ o.verio.net...
> Jackson A. Marshall wrote:
> > I have a been testing the try/catch exception mechanism
> > (as implemented by DigitalMars) and found that if I
> > throw an object its dtor gets called 3 times, if I throw
> > a reference its dtor gets called twice - and so it seems
> > practical to instantiate an object and throw its address,
> > and sure enough, its dtor gets called only once.
> >
> > This is part of the Test class implementation (contains only
> > one data member: "int n" ):
> >

> [...]
> >
> > Anyone comments?

>
> Here is a comment: regarding your code and the sequence of d-tors,
> you're throwing an address of a local variable. It gets destroyed
> before you catch it. When you after catching the value of the
> pointer attempt to use it, you get undefined behavour.
>
> And also your 'Test' class doesn't seem to have any copy c-tor
> implemented, thus making it impossible for you to track copy
> construction (not that you should expect any, but still).
>
> If you want to throw by an address (pointer), you have to use
> either a global object (that survives the stack unwinding) or
> a dynamic object (use 'new'). Of course, it's better to throw
> a temporary object and catch by a const reference.


Thanks V

I do have a copy-ctor, just didn't show it:

// Copy Constructor
Test::Test(Test& t) : n(t.n) {
++::count;
std::cout << " Test(" << ::count << ") Copy-Ctor\n";
}

Using "new" :

// e.g. Test1 += Test2;
const Test& Test:perator+=(const Test& rhs) {
std::cout << "operator+=(Test&)\n";
if(this == &rhs) {
Except* ex = new Except("operator+= self assignment!");
throw( ex );
}
n += rhs.n;
return *this;
}

// copy ctor: pass by value
void test1(Test a) {}

int main() {
Test t;
test1(t); // copy ctor
cout << "\n";

try { t += t; }
catch( Except* e) {
cout << "Throw() caught: " << e->Get() << "\n";
delete e;
return -1;
}
}

Output:
=====
Test(1)
Test(2) Copy-Ctor
~Test(2)

operator+=(Test&)
Except(1)
Throw() caught: operator+= self assignment!
~Except(1)
~Test(1)
===============

What do you mean by (and how do I construct) a "temporary object"?

>jam



 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      01-11-2005
Jackson A. Marshall wrote:
> [...]
> What do you mean by (and how do I construct) a "temporary object"?


Try

const Test& Test:perator+=(const Test& rhs) {
std::cout << "operator+=(Test&)\n";
if (this == &rhs)
throw(Except("operator+= self assignment!")); // temporary

n += rhs.n;
return *this;
}
...
int main() {
Test t;
try { t += t; }
catch(Except const &e) {
cout << "Caught " << e.Get() << endl;
}
return -1;
}

V
 
Reply With Quote
 
Jackson A. Marshall
Guest
Posts: n/a
 
      01-11-2005
"Victor Bazarov" <> wrote in message news:JhSEd.35044$ .verio.net...
> Jackson A. Marshall wrote:
> > [...]
> > What do you mean by (and how do I construct) a "temporary object"?

>
> Try
>
> const Test& Test:perator+=(const Test& rhs) {
> std::cout << "operator+=(Test&)\n";
> if (this == &rhs)
> throw(Except("operator+= self assignment!")); // temporary
>
> n += rhs.n;
> return *this;
> }
> ...
> int main() {
> Test t;
> try { t += t; }
> catch(Except const &e) {
> cout << "Caught " << e.Get() << endl;
> }
> return -1;
> }


Thanks V

I have implemented the code changes as you suggest.

Test(1)
operator+=(Test&)
Except(1)
~Except(1)
Throw() caught: operator+= self assignment!
~Except(0)
~Test(1)

...but this is incorrect with 2 Except dtors!

>jam





 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      01-11-2005
Jackson A. Marshall wrote:
> "Victor Bazarov" <> wrote in message news:JhSEd.35044$ .verio.net...
>
>>Jackson A. Marshall wrote:
>>
>>>[...]
>>>What do you mean by (and how do I construct) a "temporary object"?

>>
>>Try
>>
>> const Test& Test:perator+=(const Test& rhs) {
>> std::cout << "operator+=(Test&)\n";
>> if (this == &rhs)
>> throw(Except("operator+= self assignment!")); // temporary
>>
>> n += rhs.n;
>> return *this;
>> }
>> ...
>> int main() {
>> Test t;
>> try { t += t; }
>> catch(Except const &e) {
>> cout << "Caught " << e.Get() << endl;
>> }
>> return -1;
>> }

>
>
> Thanks V
>
> I have implemented the code changes as you suggest.
>
> Test(1)
> operator+=(Test&)
> Except(1)
> ~Except(1)
> Throw() caught: operator+= self assignment!
> ~Except(0)
> ~Test(1)
>
> ..but this is incorrect with 2 Except dtors!


Are you sure that you got every Except's _constructor_ accounted for?
What about the copy constructor?
 
Reply With Quote
 
Jackson A. Marshall
Guest
Posts: n/a
 
      01-11-2005
"Victor Bazarov" <> wrote in message news:7LTEd.35055$ o.verio.net...
>
> Are you sure that you got every Except's _constructor_ accounted for?
> What about the copy constructor?


Many thanks V

I didn't have an Except copy-ctor, but do now :

// Copy Constructor
Except::Except( const Except& ex) : data(ex.data) {
++::except;
std::cout << " Except(" << ::except << ") Copy-Ctor\n";
}

Output:
Test(1)
operator+=(Test&)
Except(1)
Except(2) Copy-Ctor
~Except(2)
Throw() caught: operator+= self assignment!
~Except(1)
~Test(1)

Thanks again
>jam




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Scope - do I need two identical classes, each with different scope? ann Java 13 09-13-2005 03:07 AM
How do namespace scope and class scope differ? Steven T. Hatton C++ 9 07-19-2005 06:07 PM
How to prevent a COM object and its associated dialog out of scope Leo C++ 1 04-30-2005 12:05 AM
Try, Try, Try, again... Rick12N4@netscape.net Computer Support 3 01-29-2005 04:02 PM
IMPORT STATIC; Why is "import static" file scope? Why not class scope? Paul Opal Java 12 10-10-2004 11:01 PM



Advertisments