How does C++ store functions and objects in memory? [duplicate]

大兔子大兔子 提交于 2019-11-28 07:22:34

问题


Lets say we have a class

class A
{
    int x;
public:
    void sayHi()
    {
        cout<<"Hi";
    }
};

int main()
{
    A *a=NULL;
    a->sayHi();
}

The above code will compile on Turbo C (where I tested) and print Hi as output.

I was expecting crash because a is NULL. More over if I make sayHi() function virtual, it says

Abnormal temination(Segmentation fault in gcc) 

I know a lot of it is implementation dependent but if anybody could throw some light on any implementation or just give an overview it would be really nice.


回答1:


Obviously, the code has undefined behavior, i.e., whatever you get is by chance. That said, the system doesn't need to know about the object when calling a non-virtual member function: It can just be called based on the signature. Further, if a member function doesn't need to access a member, it doesn't need really need an object at all and can just run. This is what you observed when the code printed some output. Whether this is how the system is implemented isn't defined, however, i.e., nothing says it works.

When calling a virtual function type system starts off looking at a type information record associated with the object. When calling a virtual function on a NULL pointer, no such information exists and attempting to access it probably leads to some sort of crash. Still, it doesn't have to but it does for most system.

BTW, main() always returns int.




回答2:


In C++, the methods of a class are not stored inside the instances of that class. They're simply some "special" functions that transparently accept the this pointer in addition to the arguments specified by the programmer.

In your case, the sayHi() method does not reference any of the class fields, therefore, the this pointer (which is NULL) is never followed.

Make no mistake, though, this is still undefined behavior. Your program may choose to send nasty emails to your contact list when you invoke this. In this particular instance, it does the worst thing, and appears to work.

The virtual method case has been added since I answered the question, but I won't refine my answer, since it's included by others' answers.




回答3:


As a generalisation, the layout of a object instantiated from a class with no super classes and virtual functions is as follows:

* - v_ptr  ---> *  pTypeInfo
|               |- pVirtualFuncA
|               |- pVirtualFuncB
|- MemberVariableA
|- MemberVariableB

v_ptr is a pointer to the v-table - which contains addresses of virtual functions and RTTI data for the object. Classes without virtual functions don't have v-tables.

In your example above, class A has no virtual methods and thus no v-table. This means the implementation of sayHi() to call can be determined at compile time and is invariant.

The compiler generates code that sets the implicit this pointer to a and then jumps to the beginning of sayHi(). Since the implementation has no need for the object's contents, the fact that it works when the pointer is NULL is a happy coincidence.

If you were to make sayHi() virtual, the compiler cannot determine the implementation to call at compiler time, so instead generates code that looks up the address of the function in the v-table and calls it. In your example where a is NULL, the compiler reads the contents of address 0, causing the abort.




回答4:


If you call a non-virtual method of a class, for the compiler it is enough to know what class the function belongs to and by dereferencing - albeit a NULL - pointer to a class to call the method, the compiler gets that information. The sayHi() method is pretty much just a function that takes pointer to the class instance as a hidden parameter. This pointer is NULL but that doesn't matter if you do not reference any attributes in the method.

The moment you make this method virtual, the situation changes. The compiler does not know what code is associated with the method at compile time any more and must figure that out at the runtime. What it does is that it looks into a table that basically contains function pointers for all virtual methods; this table is associated with the class instance so it looks at piece of the memory relative to the NULL pointer and therefore crashes in this case.



来源:https://stackoverflow.com/questions/12660829/how-does-c-store-functions-and-objects-in-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!