Re: Can an object know it is dead?
Daniel T. wrote:
In article <ern67b$bl5$1@aioe.org>, Noah Roberts <user@example.net>
wrote:
Daniel T. wrote:
In article <1172247439.625622.103690@q2g2000cwa.googlegroups.com>,
"Thomas Tutone" <Thomas8675309@yahoo.com> wrote:
Ignoring the threads aspect of this, the simplest way is to add a
private bool member and an isValid() member function:
[untested code]
class yourClass {
private:
bool valid_;
protected:
bool isValid() { return valid_; }
public:
yourClass() : valid_(true) {}
~yourClass() { valid_ = false; }
// Rest of yourClass
};
The above isn't "standards-compliant" as requested. If another object is
created in the memory space vacated by the dead object, valid_ may be
true even though the object is dead.
And how is this different than your "solution"?
With my solution, an assert will fire if some part of the code attempts
to destroy an object that is in use. I agree though that it allows one
to attempt to use an object that was destroyed and that needs to be
fixed. Here is a revised version:
map<void*, size_t> lock;
class Object {
Object() {
assert( lock.find(this) == lock.end() );
lock[this] = 0;
}
~Object() {
assert( lock[this] == 0 );
lock.erase( this );
}
void func() {
assert( lock.find(this) != lock.end() );
++lock[this];
// do work
--lock[this];
}
};
void user( Object* o ) {
assert( lock.find(o) != lock.end() );
++lock[o];
// work with 'o'
--lock[o];
}
With the above, if you attempt to destroy an object that is still being
used by someone, an assert will fire and if you attempt to create an
object in a memory location that is in use, an assert will fire.
Of course it is wise to wrap the increment and decrement in an object
(RAII)
class Locker {
const void* obj;
Locker( const void* obj ): obj(obj) {
assert( lock.find(obj) != lock.end() );
++lock[obj];
}
~Locker() {
--lock[obj];
}
};
Your fixed version is also not portable. Any and all uses of a deleted
object illicit undefined behavior. It also offers 0 protection in a
non-debug environment. Concurrent programs are affected by too many
variables for this to work even in cases when it might in a serial
program. What needs to be done here is to make sure the object is not
deleted before it is done being used. To do that, the easiest method is
some kind of smart pointer such as boost::shared_ptr (if such is thread
safe and I don't know). Even pooling could fall prey to the same
problem if a thread deletes the pool before those working with objects
in it are done.
So even by standard your solution doesn't work. When you add in the
OP's requirements it is even less suitable.