Can you tell if a C++ pointer has been destructed?
I have a global singleton that is used by many objects in my program. This is causing crashes when the program is shutting down - it is used in the destructors of some objects, after the singleton itself has been destructed by end-of-开发者_StackOverflow中文版program. Is there a portable way to tell if a pointer has had 'delete' called on it? In my case, it looks like delete changes the value of the pointer to (void*)(-1), but I don't know if this is portable.
No, it is not possible to tell if the object pointed to by a C++ pointer has been destroyed.
You can use smart pointers, which handle it automatically.
Simple Answer:
- Do not use pointers.
- Use a classic Myers singleton.
Then to guarantee it is destroyed after your object just makes sure it is instantiated before your object. To make sure it is instantiated before your object just use it in the constructor of your object.
Rule of thumb: If you want to use a singleton in the destructor. Use it in the constructor first.
class A
{
A();
A(A const&);
A& operator=(A const&);
public:
static A& getInstance() // return reference.
{
static A instance; // Created on first use.
// So lazily created when expensive.
return instance; // Guaranteed to be destroyed in reverse order of
// creation In comparison to other static storage
// duration objects. Thus if it is created before
// your object It is guaranteed to be correctly
// destroyed after your object.
// If you want to guarantee it is created before your
// object just call A::getInstance() in your constructor
// the static member 'instance' will only be created
// once and returning a reference is not expensive.
}
// If you are creating this from the constructor of a global
// Then threading becomes a non issues as threads are not started before main
// If you are using pthreads or Windows threads you potentially can start them
// but it is undefined if they will work so again not your issue.
};
Not possible and I would have thought it's an undefined area as well.
You're best bet is to not delete your singleton until after everything else has been cleaned up, otherwise set the pointer to NULL after deleting the instance and then you can check for that. It sounds to me like some refactoring is in order though.
As it has been said, no you can't. There are different techniques to track this, but they are platform dependent.
First of all, what is the actual problem in your case? You have a singleton, which is being used by other objects when they are destroyed. If your singleton is destroyed by C Runtime, what destroys the other objects?
An easy way to determine what's deleting the singleton is to simple make the singleton's destructor private. You should then get a compile error anywhere that's trying to delete it.
This code will tracking the lifetime of a static instance; works equally well if you heap allocate.
Of course, even if the instance is not yet constructed, it will be on the first call to instance()
.
However, if you have some complex mesh of global static destructors, you should be able to use this to determine whether or not the instance has been destructed.
class Thing
{
public:
enum State { preConstruction, constructed, destructed };
static const State& singletonState() { return state_;}
static Thing& instance()
{
static Thing instance;
return instance;
}
private:
Thing()
{
state_ = constructed;
}
~Thing()
{
state_ = destructed;
}
static State state_;
};
Thing::State Thing::state_ = Thing::preConstruction;
Another option is after delete
is called, set the pointer to NULL
. Then you can check if the pointer is NULL
and know that the pointer has been deleted (or hasn't been initialized yet).
class MyClass
{
public:
MyClass()
{
pPointer = new NewClass();
}
~MyClass()
{
delete pPointer;
pPointer = NULL;
}
private:
NewClass *pPointer;
}
C++ doesn't define the order in which two global constructors or destructors are called if the objects are defined in separate files. However, if objects are defined in the same file, then there is an order: file scope objects are constructed in lexical order (the order in which they appear in the file) and destroyed in the reverse order.
This can be exploited in combination with header file dependencies to bring order into C++ global construction and destruction, like this:
// header file A.h
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
class A { /* ... */ };
#ifdef DEFINE_GLOBALS
A a_singleton;
#endif
#endif
// header file B.h
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
#include "A.h"
class B : { A *pa_memb; /* ... */ }
#ifdef DEFINE_GLOBALS
B b_singleton;
#endif
#endif
// header file C.h
#ifndef C_H_INCLUDED
#define C_H_INCLUDED
#include "B.h"
#include "A.h"
class C : { A *pa_memb, B *pb_memb; /* ... */ }
#ifdef DEFINE_GLOBALS
C c_singleton;
#endif
#endif
Then, we have a file called globals.cc
where we do this:
// globals.cc
#define DEFINE_GLOBALS
#include "C.h"
#include "A.h"
#include "B.h"
The #include
guards in the headers will ensure that the inclusions in global.cc
are in the proper dependency order (and that missing ones will probably be picked up: in the above example, if we just include "C.h"
, we are good). Now all of the global objects are defined in a single translation unit and are constructed in the correct order: used objects are constructed before their users, and destroyed after their users.
精彩评论