question about objects passed into constructors

Discussion in 'C++' started by fighter1@airmail.net, Jan 16, 2004.

  1. Guest

    Hello,

    I have a question about passing an object into a constructor.

    How can I check to make sure that the object is good/valid that is
    being passed into the constructor.

    Obviously I could check to see if it is non-NULL, but that still will
    not necessarily tell me anything.

    For example:

    /* here is a constructor car that takes an engine class as an
    argument. But, I better check to make sure that engine is valid
    so how do I do that?
    */
    Car::Car( Engine* engine )
    {

    // check to make sure that engine is valid.


    }


    Thanks in advance for any help,
    John
    , Jan 16, 2004
    #1
    1. Advertising

  2. wrote:

    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that
    > the object that is being passed into the constructor is good/valid.
    >
    > Obviously I could check to see if it is non-NULL
    > but that still will not necessarily tell me anything.



    class Engine {
    private:
    // representation
    const
    unsigned int Valid;
    public:
    //functions
    bool valid(void) const {
    return 0x55555555 == Valid;
    }
    // constructors
    Engine(void): Valid(0x55555555) { }
    ~Engine(void) { Valid = 0xAAAAAAAA; }
    };

    > For example:
    >
    > // Here is a constructor car
    > // that takes an engine class as an argument.
    > // I had better check to make sure that engine is valid.
    > // How do I do that?
    >
    > Car::Car(const Engine& engine) {
    > // check to make sure that engine is valid.
    > if (engine.valid()) {
    > // Initialize *this.
    > }
    > else { /* Handle error. */ }
    > }
    E. Robert Tisdale, Jan 16, 2004
    #2
    1. Advertising

  3. In article <>, wrote:

    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.
    >
    > Obviously I could check to see if it is non-NULL, but that still will
    > not necessarily tell me anything.
    >
    > For example:
    >
    > /* here is a constructor car that takes an engine class as an
    > argument. But, I better check to make sure that engine is valid
    > so how do I do that?
    > */


    What do you mean by "valid" ? The Engine class should be responsible for making
    sure that Engine objects are not "invalid".

    Since you are passing in a pointer, you need to check for a null pointer.

    If the pointer is not null, it's the callers responsibility to pass in a valid
    pointer. There's no way to check whether a pointer is "wild" or not.

    Cheers,
    --
    Donovan Rebbechi
    http://pegasus.rutgers.edu/~elflord/
    Donovan Rebbechi, Jan 16, 2004
    #3
  4. David White Guest

    <> wrote in message
    news:...
    > Hello,
    >
    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.
    >
    > Obviously I could check to see if it is non-NULL,


    Unless it's a pointer there's nothing to check, NULL-wise.

    > but that still will
    > not necessarily tell me anything.
    >
    > For example:
    >
    > /* here is a constructor car that takes an engine class as an
    > argument. But, I better check to make sure that engine is valid
    > so how do I do that?
    > */
    > Car::Car( Engine* engine )
    > {
    >
    > // check to make sure that engine is valid.


    You'll have to ask the Engine object, if it has a member that serves that
    purposes. Other than checking whether the supposed memory the object
    occupies is real memory, which is a system-specific matter and OT here,
    there is no general way to tell if an object is valid. If the Engine itself
    can't tell you it's valid, nothing else can.

    DW
    David White, Jan 16, 2004
    #4
  5. David White Guest

    "E. Robert Tisdale" <> wrote in message
    news:...
    > wrote:
    >
    > > I have a question about passing an object into a constructor.
    > >
    > > How can I check to make sure that
    > > the object that is being passed into the constructor is good/valid.
    > >
    > > Obviously I could check to see if it is non-NULL
    > > but that still will not necessarily tell me anything.

    >
    >
    > class Engine {
    > private:
    > // representation
    > const
    > unsigned int Valid;
    > public:
    > //functions
    > bool valid(void) const {
    > return 0x55555555 == Valid;
    > }
    > // constructors
    > Engine(void): Valid(0x55555555) { }
    > ~Engine(void) { Valid = 0xAAAAAAAA; }
    > };


    Of course, with the same "valid" value used in all instances, and perhaps in
    other classes as well, it will greatly increase the probability that some
    dangling or uninitialized pointer will be unlucky enough to point somewhere
    such that the Valid member happens to be 0x55555555.

    DW
    David White, Jan 16, 2004
    #5
  6. <> skrev i en meddelelse
    news:...
    > Hello,
    >
    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.
    >
    > Obviously I could check to see if it is non-NULL, but that still will
    > not necessarily tell me anything.
    >
    > For example:
    >
    > /* here is a constructor car that takes an engine class as an
    > argument. But, I better check to make sure that engine is valid
    > so how do I do that?
    > */
    > Car::Car( Engine* engine )
    > {
    >
    > // check to make sure that engine is valid.
    >
    >
    > }
    >
    >
    > Thanks in advance for any help,
    > John



    Most probably, you need to not use a pointer:

    Car::Car(Engine const& engine)

    as this will assure a proper engine-object to be passed always.

    If "Car" does not need an engine, you could keep your present design.

    If Car needs to use an engine, but you for some reason want to keep the
    signature of the constructor (the reason for this would not be based in the
    language), You should throw from the constructor:

    Car::Car( Engine* engine)
    {
    if (!engine) throw 0; // have a proper exception here!!
    // continue construction here
    }

    but be prepared to refactor later.

    I can't really recommend Tisdales trick unless there is a compelling reason
    to do it that way (e.g. if you are not allowed to throw an exception in the
    constructor).

    /Peter
    Peter Koch Larsen, Jan 16, 2004
    #6
  7. Chris Theis Guest

    <> wrote in message
    news:...
    > Hello,
    >
    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.
    >
    > Obviously I could check to see if it is non-NULL, but that still will
    > not necessarily tell me anything.
    >

    [SNIP]

    Well, the whole problem arises from the word "valid". It depends very much
    what you define as a valid object. Testing for NULL is a way of checking
    whether a pointer is valid but this doesn't tell you whether the object,
    which this pointer points to, has a "valid = reasonable" state. If you just
    want to check whether the pointer has something to point to then this NULL
    test is fine. Otherwise you will have to define what characterizes a
    "good/valid" object state and supply some function to check this. (See
    Robert Tisdale's post).

    Cheers
    Chris
    Chris Theis, Jan 16, 2004
    #7
  8. <> skrev i meddelandet
    news:...
    > Hello,
    >
    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.


    Why would you like to do that?
    IMHO the right way to do it is that in the documentation of the class say
    something as:

    Car::Car( Engine* engine )
    Precondition: engine points to a valid Engine object.

    and leave the responsibility for this to the caller. This is the approach
    the standard library has.

    For example:
    18.6.2.3 set_unexpected
    unexpected_handler set_unexpected(unexpected_handler f) throw();
    1 Effects: Establishes the function designated by fas the current
    unexpected_handler.
    2 Requires: f shall not be a null pointer.

    --
    Dag Henriksson
    Dag Henriksson, Jan 16, 2004
    #8
  9. Daniel T. Guest

    In article <>,
    wrote:

    > Hello,
    >
    > I have a question about passing an object into a constructor.
    >
    > How can I check to make sure that the object is good/valid that is
    > being passed into the constructor.
    >
    > Obviously I could check to see if it is non-NULL, but that still will
    > not necessarily tell me anything.
    >
    > For example:
    >
    > /* here is a constructor car that takes an engine class as an
    > argument. But, I better check to make sure that engine is valid
    > so how do I do that?
    > */
    > Car::Car( Engine* engine )
    > {
    >
    > // check to make sure that engine is valid.
    >
    >
    > }


    In other words, you want to guard against someone doing something like:

    Car myCar( (Engine*) 0x543562 );

    (where 0x543562 doesn't point to an actual Engine object.) Or some such?

    There isn't much you can do about this, but here is one idea:

    class Engine {
    static std::set< Engine* > allEngines;
    public:
    static bool isValid( Engine* anEngine ) {
    return allEngines.count( anEngine ) == 1;
    }

    Engine() {
    allEngines.insert( this );
    }
    ~Engine() {
    allEngines.erase( this );
    }
    };

    Now:

    Car::Car( Engine* engine ) {
    assert( Engine::isValid( engine ) );
    //...
    }

    This is not a cheep operation! It will probably slow your program down
    tremondusly if you do this with every class. Be sure to make it so you
    can define the extra code out when you build a release version.
    Daniel T., Jan 16, 2004
    #9
  10. "Daniel T." <> skrev i meddelandet
    news:p...
    > In other words, you want to guard against someone doing something like:
    >
    > Car myCar( (Engine*) 0x543562 );
    >
    > (where 0x543562 doesn't point to an actual Engine object.) Or some such?
    >
    > There isn't much you can do about this, but here is one idea:


    Your idea will probably work on some implementation, but technically is the
    effect of using an invalid pointer value undefined and could cause a
    system-generated runtime fault.

    That means that you can not check if a pointer argument is valid or not
    inside a function (or anywhere else). When the pointer is passed to the
    function (by value) we have already invoked undefined behavior.

    --
    Dag Henriksson
    Dag Henriksson, Jan 16, 2004
    #10
  11. jeffc Guest

    "Peter Koch Larsen" <> wrote in message
    news:4007a96a$0$247$...
    > If Car needs to use an engine, but you for some reason want to keep the
    > signature of the constructor (the reason for this would not be based in

    the
    > language), You should throw from the constructor:
    >
    > Car::Car( Engine* engine)
    > {
    > if (!engine) throw 0; // have a proper exception here!!
    > // continue construction here
    > }
    >
    > but be prepared to refactor later.
    >
    > I can't really recommend Tisdales trick unless there is a compelling

    reason
    > to do it that way (e.g. if you are not allowed to throw an exception in

    the
    > constructor).


    Yeah, but there is also the requirement that the pointer is "good/valid".
    Depending on what the OP meant, your check doesn't guarantee that either.
    jeffc, Jan 16, 2004
    #11
  12. Chris Theis wrote:

    > Well, the whole problem arises from the word "valid".
    > It depends very much what you define as a valid object.
    > Testing for NULL is a way of checking whether a pointer is valid
    > but this doesn't tell you whether the object to which
    > this pointer points has a "valid = reasonable" state.
    > If you just want to check
    > whether the pointer has something to point to,
    > then this NULL test is fine.
    > Otherwise, you will need to define
    > what characterizes a "good/valid" object state
    > and supply some function to check this.
    > (See Robert Tisdale's post).


    A NULL pointer is valid pointer which always points to
    an invalid object of any type.
    There is, unfortunately, *no* way to determine whether
    any other pointer (valid or not) references a valid object.
    If every attempt to access an invalid object through a pointer
    resulted in a segmentation fault, a bus error
    or some other system error, there would be no problem.
    The problem is that your program may access
    and, perhaps, corrupt other valid data in your program.
    It may also access an object that you have already deleted
    but which has not been reallocated and reinitialized
    so you must stamp it with a bit pattern which marks it invalid
    when the program calls your constructor.
    E. Robert Tisdale, Jan 16, 2004
    #12
  13. Dag Henriksson wrote:

    > Your idea will probably work on some implementation, but technically is the
    > effect of using an invalid pointer value undefined and could cause a
    > system-generated runtime fault.
    >
    > That means that you can not check if a pointer argument is valid or not
    > inside a function (or anywhere else). When the pointer is passed to the
    > function (by value) we have already invoked undefined behavior.


    I think that you missed the point.
    A system-generated runtime fault can be trapped
    and your program can recover or abort.
    The problem occurs when no fault is generated
    and your program initializes a Car object with an invalid Engine object.
    E. Robert Tisdale, Jan 16, 2004
    #13
  14. Guest

    "Dag Henriksson" <> wrote in message news:<bu8suq$e64hs$-berlin.de>...
    [snip of a "registering new'ed objects" system]
    > Your idea will probably work on some implementation, but technically is the
    > effect of using an invalid pointer value undefined and could cause a
    > system-generated runtime fault.
    >
    > That means that you can not check if a pointer argument is valid or not
    > inside a function (or anywhere else). When the pointer is passed to the
    > function (by value) we have already invoked undefined behavior.


    Is it still undefined behaviour if I never dereference the pointer?
    I agree it is certainly undefined if I try to access memory an
    invalid pointer points at as though it were valid. But simply passing
    an invalid pointer value through a function call is undefined?
    Just checking...
    Socks
    , Jan 16, 2004
    #14
  15. Ron Natalie Guest

    <> wrote in message news:...

    >
    > Is it still undefined behaviour if I never dereference the pointer?
    > I agree it is certainly undefined if I try to access memory an
    > invalid pointer points at as though it were valid. But simply passing
    > an invalid pointer value through a function call is undefined?
    > Just checking...


    Yes it is. It's possible (though I've never seen a machine where this
    happens) where merely copying an out of range pointer might trap.
    Ron Natalie, Jan 16, 2004
    #15
  16. lilburne Guest

    David White wrote:

    >
    >
    > Of course, with the same "valid" value used in all instances, and perhaps in
    > other classes as well, it will greatly increase the probability that some
    > dangling or uninitialized pointer will be unlucky enough to point somewhere
    > such that the Valid member happens to be 0x55555555.
    >


    You can be unlucky in many ways, but the scheme above in my
    experience catches 99.99999% of bugs due to accessing
    deleted objects. And they are usually caught the first time
    the offending code is exercised. Personally I'd assert the
    validity in every method too.
    lilburne, Jan 17, 2004
    #16
  17. "jeffc" <> skrev i en meddelelse
    news:...
    >
    > "Peter Koch Larsen" <> wrote in message
    > news:4007a96a$0$247$...
    > > If Car needs to use an engine, but you for some reason want to keep the
    > > signature of the constructor (the reason for this would not be based in

    > the
    > > language), You should throw from the constructor:
    > >
    > > Car::Car( Engine* engine)
    > > {
    > > if (!engine) throw 0; // have a proper exception here!!
    > > // continue construction here
    > > }
    > >
    > > but be prepared to refactor later.
    > >
    > > I can't really recommend Tisdales trick unless there is a compelling

    > reason
    > > to do it that way (e.g. if you are not allowed to throw an exception in

    > the
    > > constructor).

    >
    > Yeah, but there is also the requirement that the pointer is "good/valid".
    > Depending on what the OP meant, your check doesn't guarantee that either.
    >
    >


    Well... there is no way to check if a pointer is valid in C++. It better
    always be.

    /Peter
    Peter Koch Larsen, Jan 17, 2004
    #17
  18. Old Wolf Guest

    > > How can I check to make sure that
    > > the object that is being passed into the constructor is good/valid.

    >
    > class Engine {
    > private:
    > // representation
    > const
    > unsigned int Valid;
    > public:
    > //functions
    > bool valid(void) const {
    > return 0x55555555 == Valid;


    Signed-unsigned comparison.

    > }
    > // constructors
    > Engine(void): Valid(0x55555555) { }
    > ~Engine(void) { Valid = 0xAAAAAAAA; }
    > };


    I thought this was a troll at first, but others seem to have replied
    to it seriously. Any standards-conforming compiler could optimise
    away valid() entirely:

    If UB has not been invoked, then valid() must return true.
    If UB has been invoked, the program can do anything (specifically,
    make valid() return true).

    NB. I am ignoring (as you have) the case 0x55555555 > UINT_MAX.
    However I suspect in this case valid() would always be false,
    hence it can be optimised away still.

    NB2. In a newsgroup for Standard C++, I think this construct
    is fairly off-topic.
    Old Wolf, Jan 19, 2004
    #18
  19. lilburne Guest

    Old Wolf wrote:

    >
    > I thought this was a troll at first, but others seem to have replied
    > to it seriously. Any standards-conforming compiler could optimise
    > away valid() entirely:
    >


    Only if someone has been silly enough to inline it. The example just
    gives a flavour of how one might test the objects pulse. Mostly 'valid'
    would be a class, with all its members defined outline, and an
    assert_ok() method which asserts on failure.
    lilburne, Jan 19, 2004
    #19
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dee
    Replies:
    9
    Views:
    505
    Joseph Byrns
    Apr 15, 2005
  2. Dave Rudolf
    Replies:
    12
    Views:
    8,276
    Martijn Lievaart
    Feb 6, 2004
  3. Anand
    Replies:
    2
    Views:
    898
    Anand
    Sep 11, 2003
  4. Jeremy Smith
    Replies:
    2
    Views:
    587
    Jeremy Smith
    Aug 3, 2006
  5. Jess
    Replies:
    5
    Views:
    596
    Ron Natalie
    Jun 7, 2007
Loading...

Share This Page