Why doesn't the program crash when I call a me

2020-01-31 07:01发布

#include "iostream"
using namespace std;
class A
{
public:
    void mprint()
    {
        cout<<"\n TESTING NULL POINTER";
    }
};

int main()
{
    A *a = NULL;
    a->mprint();
    return 0;
}

I am getting output as "TESTING NULL POINTER". Can anyone please explain why this program is printing the output instead of crashing. I checked it on Dev C++ and aCC compiler both gave same result.

6条回答
疯言疯语
2楼-- · 2020-01-31 07:21

According to the C++ spec, This program has undefined behavior because you're invoking a member function on a null receiver.

The reason that this works, though, is that non virtual member functions are typically implemented as regular functions that take the "this" pointer as an implicit first argument. Consequently, if you call a member function on a null pointer, as long as you don't use the this pointer, your program will not crash. Of course, you cannot rely n this; a valid C++ compiler could cause this to crash.

However, virtual functions are a different story because the function that actually gets called needs to be resolved at runtime. This usually involves introspecting on the receiver's virtual function table. Thus if you try calling a virtual member function on a null pointer, even if te function doesn't access this, it will still cause a crash. Try this out if you're curious!

查看更多
贼婆χ
3楼-- · 2020-01-31 07:23

Simple Answer: Because mprint() is not using any of the member variables of the class

Detailed Answer: When a method of a class is called, class instance is passed on to the callee function (normally as the first argument, however, in some calling conventions such as __thiscall, this is passed in a register). This class instance is used to access all the member variables that are used in the callee method.

In this case, this instance is NULL but this doesnt make any difference since no member variables are being used in the callee method. Try changing your code such that you print the value of a member variable in mprint() method and you will get the crash.

查看更多
够拽才男人
4楼-- · 2020-01-31 07:36

You're not using any member variables of A - the function is completely independent of the A instance, and therefore the generated code happens to not contain anything that dereferences 0. This is still undefined behavior - it just may happen to work on some compilers. Undefined behavior means "anything can happen" - including that the program happens to work as the programmer expected.

If you e.g. make mprint virtual you may get a crash - or you may not get one if the compiler sees that it doesn't really need a vtable.

If you add a member variable to A and print this, you will get a crash.

查看更多
Fickle 薄情
5楼-- · 2020-01-31 07:37

The results of calling a member function using a null pointer to an object is undefined behavour in c++ so it can do anything.

In this case it's likely because it's rewritten your function as it it was like this

void mprint(A* this);

and your call like this

mprint(0);

So it's just called it as if it was an ordinary function and passed the null pointer as a parameter which you never then actually use in any way. That explains why it doesn't crash, but the compiler is free to do pretty much anything

查看更多
Lonely孤独者°
6楼-- · 2020-01-31 07:39

Being able of invoking non-virtual member functions on non-valid pointers even enables encoding the information associated to an object in the pointer itself. For example:

#include <iostream>

class MagicInteger {

  public:

   static MagicInteger* fromInt (int x) {
     return reinterpret_cast<MagicInteger*>(x);
   }

   int getValue() {
     return static_cast<int>(reinterpret_cast<intptr_t>(this));
   }       

  private:
   // forbid messing around
   MagicInteger ();  
   MagicInteger (MagicInteger&);
   MagicInteger& operator=(const MagicInteger&);
};

int main (void) {
  MagicInteger* i = MagicInteger::fromInt(6);
  std::cout << "Value is " << i->getValue() << std::endl;
  return 0;
}

This can also be used to implement tagged pointers, that is, pointers that contain meta-information about the pointee.

These two idioms are used in Google Chrome's javascript VM V8 to represent 31-bit integers

查看更多
Animai°情兽
7楼-- · 2020-01-31 07:44

This is completely legal call.

lets understand how it works

when a new object is creates its member variables are created.

What about member functions? Member function are not allocated news there is always one copy of all member function. By default a member variable is added to every member function that is this pointer which is pointing to the object itself.
When there is no object present that is object pointer is null value. It doenst matter because you are not accesssing it any way. You will get in problems if you use this pointer of any of the member variable in the method. This is because member variable are not valid in case of null pointer.

in MFC we have GetSafeHwnd() method for CWnd. This works on same principle.

查看更多
登录 后发表回答