Thread: Protecting Constructors

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    43

    Protecting Constructors

    Hi,

    Is there any way to "protect" class constructors? So that a function which has a pointer to a class object can't just run the constructor again to mess up the class internals?

    I had the idea of doing something like:

    Code:
    class TClass {
    private:
    int CreatedHash;
    ...
    public:
    TClass();
    ...
    };
    
    TClass::TClass()
    {
     if (CreatedHash == 93245) return;
     ...
     CreatedHash = 93245;
    }
    This kind of thing ensures that a constructor can only be run once? Well, sort of. The value of "CreatedHash" in the above example is undefined at the time of the if statement. So it is technically possible for the value to be exactly 93245, and so the program would probably crash. So in all, while this is a possible method of protecting constructors, it is not a very good one.

    Surely there is a better way?
    Windows XP Professional SP2, Code::Blocks Studio 1.0rc2, GCC/G++ 3.4.2 (20040916-1), mingw32-make 3.80.0-3, GDB 5.2.1-1, W32API 3.6

    MingW Runtime 3.9, BinUitls 2.15.91 (20040904-1), MingW Utilities 0.3, Tcl/Tk 8.4.1-1

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Although I don't see how one could construct the very same object more than once, may-be you might be interested in Singletons, not letting user create more than one instance of a class.

  3. #3
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Perhaps a singleton would be appropriate. For example:
    Code:
    class TClass {
    private:
    protected:
      TClass(); 
      TClass(TClass const&);
      TClass& operator = (TClass const&);
    ...
    public:
      static TClass* GetTheOneAndOnlyTClassInstance()
      {
      static TClass singleton;
      return &singleton;
      }
    };
    edit: beaten by anon; same linky, too.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  4. #4
    Registered User
    Join Date
    Oct 2005
    Posts
    43
    Quote Originally Posted by anon
    Although I don't see how one could construct the very same object more than once
    Like this:

    Code:
    //...
    
    TClass c(2, 56);
    
    //c is now constructed.
    
    //...
    
    //This sort of thing appears inside of a function.
    c.TClass(5, 109);
    
    //oh dear, i've messed up the class internals now.
    I do actually want to have more than one instance of the class in question, it's just that the class's constructor can't be run more than once.

    Maybe one way around would be to overload the new operator?
    Windows XP Professional SP2, Code::Blocks Studio 1.0rc2, GCC/G++ 3.4.2 (20040916-1), mingw32-make 3.80.0-3, GDB 5.2.1-1, W32API 3.6

    MingW Runtime 3.9, BinUitls 2.15.91 (20040904-1), MingW Utilities 0.3, Tcl/Tk 8.4.1-1

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I tried something like that: the line you are worried about produces a compiler error (invalid use of class...).

    If you could do something like that, the whole idea of data hiding would lose meaning. You could always call the constructor to access the private data directly.

    I don't understand the question: may-be you want to make your object non-copiable (declare a private copy constructor)?

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> it's just that the class's constructor can't be run more than once.
    The class's constructor cannot be called more than once, so you are fine.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by kidburla
    Like this:
    Code:
    //...
    
    TClass c(2, 56);
    
    //c is now constructed.
    
    //...
    
    //This sort of thing appears inside of a function.
    c.TClass(5, 109);
    
    //oh dear, i've messed up the class internals now.
    This sort of thing is disallowed anyway, as constructors cannot be invoked like other member functions (they cannot be found during function name lookup).

  8. #8
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    You can do something with this to simulate a re-construction

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    43
    Quote Originally Posted by Daved
    >> it's just that the class's constructor can't be run more than once.
    The class's constructor cannot be called more than once, so you are fine.
    Okay. Now what about Destructors? Again I had an idea to make sure that the function which created the object is the only one which can destroy it:

    Code:
    class TClass {
    private:
    int CreationKey;
    int DestructionKey;
    //...
    public:
    TClass(int xCreationKey);
    ~TClass();
    void AboutToDestroy(int xDestructionKey);
    //...
    };
    
    TClass::TClass(int xCreationKey)
    {
     CreationKey = xCreationKey;
     DestructionKey = 0;
    //...
    }
    
    TClass::~TClass()
    {
     if (DestructionKey != CreationKey) return;
     //Do the destruction stuff.
    }
    
    void TClass::AboutToDelete(int xDestructionKey)
    {
     DestructionKey = xDestructionKey;
     return;
    }
    
    void SomeFunction()
    {
     TClass *c;
    
     c = new TClass(92847);
    
     //do stuff, including passing c to other functions which don't know the creation key.
    
     c.AboutToDelete(92847);
     delete c;
    
    }
    However, I think that returning from the destructor will still cause the memory from the class to be free'd. So I thought of overloading the delete instruction, though I'm not sure how that would work.
    Windows XP Professional SP2, Code::Blocks Studio 1.0rc2, GCC/G++ 3.4.2 (20040916-1), mingw32-make 3.80.0-3, GDB 5.2.1-1, W32API 3.6

    MingW Runtime 3.9, BinUitls 2.15.91 (20040904-1), MingW Utilities 0.3, Tcl/Tk 8.4.1-1

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You could make the destructor private, and then make the function that is allowed to delete it a friend.

  11. #11
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Why are actually asking these questions?

    Are you afraid you might delete the object yourself by accident in some other function? - If you are determined to shoot in your leg, there's nothing to stop you. With the stuff you are doing, it's just going to be a lot easier than it normally would.

    Are you hoping to stop the end user from deleting an object if they don't know the deletionKey? - Then change the program logic, so that the object wouldn't go out of scope.

    Anyway, constructors and destructors are called automatically. I hardly believe you can stop the destructor from doing its stuff, once it has been called. Normally this happens when the object simply goes out of scope. If the object goes out of scope, but the destructor doesn't get the chance to do the destructing (because it doesn't have the right deletionKey), what do you expect to happen? A memory leak? Undefined behaviour?

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by twomers
    You can do something with this to simulate a re-construction
    Yeah, but the technique to do that has a very specific application. That technique is rarely used for two reasons: firstly, it is something that is needed very rarely and, secondly, it yields undefined behaviour unless a very specific set of conditions are met. kidburla's code example doesn't even come close.

    It is not possible to stop an object from invoking it's destructor and then attempting to reconstruct itself in place. But such things are in the control of the class implementer -- and rarely used, as one of the instances where it will often yield undefined behaviour is in a class hierarchy (i.e. any classes are derived from the one using the technique). It would be a very rare user of the class (i.e. progammer writing code that is not a class member function or a friend) that would have any reason to use the technique coupled with the know-how to do so. It would be even rarer for those conditions to be associated with the stupidity to use the technique without access to detailed knowledge of the class implementation.
    Last edited by grumpy; 10-15-2006 at 02:08 AM.

  13. #13
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    I'll second anon's question. In both this thread and your previous, you go to extreme and convoluted lengths to try to prevent abuse of your class. Realistically, it's not possible to prevent a user who is bound and determined to blow things up in his face. You're creating worse problems than the ones you try to prevent.

    You can't make code idiotproof. The compiler can only do so much, a truly determined user can circumvent any of the checks the compiler does.

    Creative pointer recasting could allow them to simply read the hash out of your object, if that was their choice. That hash is stored at a particular offset inside the object, they can cast the object * into void * and then memcpy the hash out. Clever code could even autodetect the offset to the hash. For example:

    Code:
    void EvilFunction(TClass * innocent){
    
    	TClass * sacrifice = new TClass(0xDEADBEEF);
    	char * base = (char *) sacrifice;
    	int offset;
    
    	for (offset = 0; * (int *)(base + offset) != 0xDEADBEEF; offset++){}
    
    	// Here, you could destroy sacrifice, its purpose is done.
    
    	base = (char *) innocent;
    	std::cout << "The secret key is: "  << * (int *) (base + offset)<< std::endl;
    
    }
    If your code is so sensitive that you absolutely cannot permit the user of your class to have any possibility of manipulating the internals of your objects maliciously, your code should not be running in the same process (and probably not even on the same machine) as their code. In such a scenario (e.g. writing an application that has limited access to a database) make it client-server, where you code the server and rigorously validate any input from the client.

    If the only problem with another programmer using your class and deleting your pointer would be that the program that person's writing is buggy, well, that's their own damn fault then. You can't make some kind of nerf class that's completely impossible for the user to hurt themselves on.
    Last edited by Cat; 10-15-2006 at 12:09 AM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Copy constructors; Best practices (and private)
    By Mario F. in forum C++ Programming
    Replies: 15
    Last Post: 06-23-2006, 04:42 PM
  2. constructors, arrays, and new
    By Thantos in forum C++ Programming
    Replies: 6
    Last Post: 05-30-2004, 06:21 PM
  3. Throwing exceptions with constructors
    By nickname_changed in forum C++ Programming
    Replies: 14
    Last Post: 07-08-2003, 09:21 AM
  4. Copy constructors and private constructors
    By Eibro in forum C++ Programming
    Replies: 5
    Last Post: 11-24-2002, 10:16 AM
  5. Default Constructors
    By MethodMan in forum C++ Programming
    Replies: 2
    Last Post: 10-25-2002, 06:30 PM