resource acquisition is initialization?

Y

yang su

I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

I use g++ 3.2.3 on solaris 2.8, thanks.

yang





#include <string>
#include <iostream>

using namespace std;

class T {
private:
string name;

public:
T(const string& name) {
this->name = name;
cout<<"allocate resource for " << name << endl;
if( name.compare("banana") == 0 ) {
throw exception();
}
}

operator string() {
return name;
}

~T() {
cout<<"deallocate resource from " << name << endl;
}
};


class User {
private:
T t1, t2;

public:
User(const string& s, const string& p): t1(s), t2(p) {
cout<<"user inited" << endl;
try{
throw exception();
}catch(exception& e) {
}
}

void use( ) {
cout<< "use "<< (string)t1 << " and " << (string)t2 <<
endl;
throw exception();
}

~User() {
cout <<"user destroyed" << endl;
}
};


int main(int argc, char **argv) {
/*
User *u = NULL;
if( argc >= 3 ) {
if( argc > 3 ) {
User x(argv[1], argv[2]);
x.use();
return 0;
}
}
u = new User( argv[1], argv[2] );
}else{
u = new User(string("apple"), string("banana"));
}

u->use();
delete u;
*/


User u("apple", "banana");
u.use();
}
 
V

Victor Bazarov

yang said:
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

I use g++ 3.2.3 on solaris 2.8, thanks.

Could be a bug in the compiler. I surrounded the contents of 'main'
with try {} catch(...) {} to prevent unhandled exception, and it worked
as expected under VC++ 7.1

Victor
 
R

Rolf Magnus

yang said:
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

I think the problem is that you don't catch the exception. If an
uncaught exception is found, the process is terminated before the
variable can be destroyed. If I add a try/catch block in main around
the creation and usage of u, the object gets destroyed as expected.
 
M

Marco Manfredini

yang said:
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

Not quite. t2 throws an exception for which no exception handler exist.
If something like that happens, the runtime system has to call the
terminate() function, which aborts the program. The fine point is: The
c++ standard says, that it is implementation defined, whether the stack
is unwound or not in this case!

So if you want guaranteed clean-up even in case of not-having an
appropriate exception handler, you'll have to wrap anything into a
catchall block:

int main()
try {
User u("apple", "banana");
u.use();
}
catch(...)
{
// call abort() or terminate() as you like..
}

Marco
 
J

John Harrison

yang su said:
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

I use g++ 3.2.3 on solaris 2.8, thanks.

yang

[snip]


class User {
private:
T t1, t2;

It is not defined whether t1 or t2 is constructed first. Only if t1 is
constructed before t2 will an exception in t2 cause the destructor for t1 to
be called.

Try this

T t1;
T t2;

Now t1 must be constructed before t2.

john
 
R

Rolf Magnus

Rolf said:
That's wrong. t1 is constructed first.

Hmm, ok. I'm not sure about that actually. You mean the order is not
defined because they are declared as T t1, t2; instead of T t1; T t2;?
 
J

John Harrison

Rolf Magnus said:
Hmm, ok. I'm not sure about that actually. You mean the order is not
defined because they are declared as T t1, t2; instead of T t1; T t2;?

That's what I mean, but I'm relying on my sometimes faulty recollection.
I'll look it up later.

John
 
V

Victor Bazarov

John said:
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen.

I use g++ 3.2.3 on solaris 2.8, thanks.

yang


[snip]


class User {
private:
T t1, t2;


It is not defined whether t1 or t2 is constructed first.

Really? Care to elaborate or give a quote from the Standard? For some
reason I always thought that initialisation (construction) happens in the
order of declaration. Besides, in a declaration statement there is
a sequence point after every declarator.
Only if t1 is
constructed before t2 will an exception in t2 cause the destructor for t1 to
be called.

Try this

T t1;
T t2;

Now t1 must be constructed before t2.

john

I _really_ think there is no difference between

A a, b;

and

A a; A b;

It would be illogical to have them behave differently depending on where
the declaration happens.

V
 
M

Marcelo Pinto

I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen. [snip]
int main(int argc, char **argv) { [snip]

User u("apple", "banana");
u.use();
}

Wasn't this the expected behavior? I would bet that the object u would
not be destroyed (destructor called) since an exception was thrown
during its creation (construction). Isn't this the prescribed
behavior?

Marcelo Pinto.
 
R

Rolf Magnus

Marcelo said:
(e-mail address removed) (yang su) wrote in message
I have a very simple program listed below, which basically tries to
use resources but prevent from memory leak should exception occurs.
class T is the resource and class User is to use the resource, my
expectation is that when t2 fails, the destructor of t1 should be
called, which didn't happen. [snip]
int main(int argc, char **argv) { [snip]

User u("apple", "banana");
u.use();
}

Wasn't this the expected behavior? I would bet that the object u would
not be destroyed (destructor called) since an exception was thrown
during its creation (construction). Isn't this the prescribed
behavior?

Each fully constructed object gets its destructor called, and u.t1 is
fully constructed at the point of the exception.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top