Able to call member function with a pointer assigned NULL

Discussion in 'C++' started by nsharma78@gmail.com, Apr 11, 2006.

  1. Guest

    Hi,

    I have a code as follows:

    class A
    {
    public:
    void print(){cout << "Magic" << endl;}
    };

    int main()
    {
    A* ptrA = NULL;
    ptrA->print();
    }


    The out put is given as Magic.

    I wanted to know why is it happening.
    In case i add one data member to the class say int i;
    then this code will not work.

    Can any body explain why?

    Thanks
    , Apr 11, 2006
    #1
    1. Advertising

  2. Noah Roberts Guest

    wrote:
    > Hi,
    >
    > I have a code as follows:
    >
    > class A
    > {
    > public:
    > void print(){cout << "Magic" << endl;}
    > };
    >
    > int main()
    > {
    > A* ptrA = NULL;
    > ptrA->print();
    > }
    >
    >
    > The out put is given as Magic.
    >
    > I wanted to know why is it happening.
    > In case i add one data member to the class say int i;
    > then this code will not work.
    >
    > Can any body explain why?


    Calling a function on an invalid pointer illicits undefined behavior.
    Noah Roberts, Apr 11, 2006
    #2
    1. Advertising

  3. Marcus Kwok Guest

    wrote:
    > class A
    > {
    > public:
    > void print(){cout << "Magic" << endl;}
    > };
    >
    > int main()
    > {
    > A* ptrA = NULL;
    > ptrA->print();
    > }
    >
    >
    > The out put is given as Magic.
    >
    > I wanted to know why is it happening.


    You have UB, which means anything can happen.

    Member functions are basically regular functions with a hidden "this"
    parameter, so in a situation like you gave above, it is possible that it
    will work. However, if you add a data member and try to access it, then
    you will almost certainly get a crash.

    Do not rely on this behavior. Dereferencing a null pointer is always a
    bad idea.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
    Marcus Kwok, Apr 11, 2006
    #3
  4. Andre Kostur Guest

    Marcus Kwok wrote:
    > wrote:
    >> class A
    >> {
    >> public:
    >> void print(){cout << "Magic" << endl;}
    >> };
    >>
    >> int main()
    >> {
    >> A* ptrA = NULL;
    >> ptrA->print();
    >> }
    >>
    >>
    >> The out put is given as Magic.
    >>
    >> I wanted to know why is it happening.

    >
    > You have UB, which means anything can happen.
    >
    > Member functions are basically regular functions with a hidden "this"
    > parameter, so in a situation like you gave above, it is possible that it
    > will work. However, if you add a data member and try to access it, then
    > you will almost certainly get a crash.
    >
    > Do not rely on this behavior. Dereferencing a null pointer is always a
    > bad idea.


    However, could you tell us what platform and compiler this was on so
    that we can easily hold it up as an example of how undefined behaviour
    can blow up? (I haven't seen this particular type of undefined
    behaviour fail before, unless you attempt to reference a member variable
    from within the method that was called.)
    Andre Kostur, Apr 11, 2006
    #4
  5. Marcus Kwok Guest

    Andre Kostur <> wrote:
    > Marcus Kwok wrote:
    >> wrote:
    >>> class A
    >>> {
    >>> public:
    >>> void print(){cout << "Magic" << endl;}
    >>> };
    >>>
    >>> int main()
    >>> {
    >>> A* ptrA = NULL;
    >>> ptrA->print();
    >>> }
    >>>
    >>>
    >>> The out put is given as Magic.

    >>
    >> You have UB, which means anything can happen.
    >>
    >> Member functions are basically regular functions with a hidden "this"
    >> parameter, so in a situation like you gave above, it is possible that it
    >> will work. However, if you add a data member and try to access it, then
    >> you will almost certainly get a crash.
    >>
    >> Do not rely on this behavior. Dereferencing a null pointer is always a
    >> bad idea.

    >
    > However, could you tell us what platform and compiler this was on so
    > that we can easily hold it up as an example of how undefined behaviour
    > can blow up? (I haven't seen this particular type of undefined
    > behaviour fail before, unless you attempt to reference a member variable
    > from within the method that was called.)


    Honestly, it works on all four systems I just tried it on, but that's
    the problem with UB: It can do anything, including exactly what you
    expect it to do. However, I will stick to my stance that relying on UB
    is generally not a good idea.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
    Marcus Kwok, Apr 11, 2006
    #5
  6. Guest

    I know that it is UB. I was just curious how that function is executed
    thru a NULL pointer.
    It seems that this function is as good as a non-member function
    executing at its own and do not require any valid pointer.

    but whenever we add a data member it simply crashes.

    I just wanted to know what causes that crash and why it is necessary to
    add a data member to re-produce that crash.

    Thanks,

    Marcus Kwok wrote:
    > Andre Kostur <> wrote:
    > > Marcus Kwok wrote:
    > >> wrote:
    > >>> class A
    > >>> {
    > >>> public:
    > >>> void print(){cout << "Magic" << endl;}
    > >>> };
    > >>>
    > >>> int main()
    > >>> {
    > >>> A* ptrA = NULL;
    > >>> ptrA->print();
    > >>> }
    > >>>
    > >>>
    > >>> The out put is given as Magic.
    > >>
    > >> You have UB, which means anything can happen.
    > >>
    > >> Member functions are basically regular functions with a hidden "this"
    > >> parameter, so in a situation like you gave above, it is possible that it
    > >> will work. However, if you add a data member and try to access it, then
    > >> you will almost certainly get a crash.
    > >>
    > >> Do not rely on this behavior. Dereferencing a null pointer is always a
    > >> bad idea.

    > >
    > > However, could you tell us what platform and compiler this was on so
    > > that we can easily hold it up as an example of how undefined behaviour
    > > can blow up? (I haven't seen this particular type of undefined
    > > behaviour fail before, unless you attempt to reference a member variable
    > > from within the method that was called.)

    >
    > Honestly, it works on all four systems I just tried it on, but that's
    > the problem with UB: It can do anything, including exactly what you
    > expect it to do. However, I will stick to my stance that relying on UB
    > is generally not a good idea.
    >
    > --
    > Marcus Kwok
    > Replace 'invalid' with 'net' to reply
    , Apr 11, 2006
    #6
  7. Andre Kostur Guest

    wrote:
    > I know that it is UB. I was just curious how that function is executed
    > thru a NULL pointer.
    > It seems that this function is as good as a non-member function
    > executing at its own and do not require any valid pointer.
    >
    > but whenever we add a data member it simply crashes.


    Back to my curiosity question of what platform and compiler is this?
    Just so we (clc++) can use it as an example of where this specific
    instance of UB crashes the program.

    > I just wanted to know what causes that crash and why it is necessary to
    > add a data member to re-produce that crash.


    Not to sound snarky, but why do you care? Since attempting to call a
    method through a NULL pointer invokes Undefined Behviour, regardless of
    whatever the content of your class is, why does it matter when it
    crashes? (I explained why _I_ want to know when this crashes....)

    However, the nutshell version (and definitely implementation-specific)
    is that in most cases the compiler converts function calls of the form:

    obj->method(param1, param2);

    into something resembling:

    method(obj, param1, param2);


    Inside method(), the first parameter(obj) gets assigned to the "this"
    pointer, and the rest of the parameters are dealt with as normal.

    However, simply adding a member variable "shouldn't" cause anything to
    blow up unless you attempt to access that variable within the method.
    Up to that point you haven't (necessarily) caused the program to attempt
    to dereference the NULL pointer. If you tried to access the member
    variable:

    a = 4;

    That would be "converted" to:

    this->a = 4;

    This would have to dereference the NULL pointer, and attempt to assign 4
    into whatever appropriate memory location relative to NULL that a
    happens to lie on (and is likely not writable memory...).

    And more things start coming into play if method() happens to be virtual....

    Again, all of this is conjecture, and compiler implementors can
    implement all of this in whatever way they choose. It all boils down
    to: Calling methods through a NULL pointer is Undefined Behaviour.
    Andre Kostur, Apr 11, 2006
    #7
  8. Ben C Guest

    On 2006-04-11, <> wrote:

    > [...]
    > class A
    > {
    > public:
    > void print(){cout << "Magic" << endl;}
    > };
    >
    > int main()
    > {
    > A* ptrA = NULL;
    > ptrA->print();
    > }


    > I know that it is UB. I was just curious how that function is executed
    > thru a NULL pointer.


    > It seems that this function is as good as a non-member function
    > executing at its own and do not require any valid pointer.
    >
    > but whenever we add a data member it simply crashes.
    >
    > I just wanted to know what causes that crash and why it is necessary to
    > add a data member to re-produce that crash.
    > [...]


    The function print() is non-virtual, and so the compiler doesn't need to
    dereference ptrA to find the function print. It would be generating
    unnecessarily inefficient code if it did. So the call to ptrA->print()
    doesn't actually require dereferencing ptrA at all. It's just a call to
    A::print() with the parameter 0 in "this".

    Of course, as soon as you access a data member in the body of print(),
    the program will access 0->data_ and that's when it'll very likely
    crash.

    I think it probably is defined that a class with no virtual functions
    has no vtable.

    Still calling a method of 0 probably is undefined behaviour anyway.
    Ben C, Apr 18, 2006
    #8
  9. Gavin Deane Guest

    Ben C wrote:
    > I think it probably is defined that a class with no virtual functions
    > has no vtable.


    If by "defined" you mean "required by the standard" then, no that's not
    defined. The standard doesn't say anything about vtables at all. I'd be
    surprised if any compiler that elected to implement polymorphism
    through vtables also put a vtable in a class with no virtual functions
    though.

    > Still calling a method of 0 probably is undefined behaviour anyway.


    It's definitely undefined behaviour. Always.

    Gavin Deane
    Gavin Deane, Apr 19, 2006
    #9
    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. Fraser Ross
    Replies:
    4
    Views:
    1,023
    Fraser Ross
    Aug 14, 2004
  2. ww
    Replies:
    4
    Views:
    377
    James Kanze
    Oct 26, 2007
  3. aneuryzma
    Replies:
    3
    Views:
    690
    Jim Langston
    Jun 16, 2008
  4. Christopher
    Replies:
    4
    Views:
    425
    Ruben Safir
    Jul 9, 2011
  5. somenath
    Replies:
    2
    Views:
    143
    somenath
    Aug 29, 2013
Loading...

Share This Page