问题
Possible Duplicate:
C++: why is new needed?
Why cant I use malloc to allocate space for my objects when they are children of a class containing virtual functions? This is really frustrating. Is there a good reason?
The following program illustrates the problem. It segfaults on line 27, where I call aa->f()
#include <iostream>
#include <cstdlib>
class A
{
public:
virtual int f() {return 1;}
};
class B
{
public:
int f() {return 1;}
};
class Aa : public A {};
class Bb : public B {};
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
return 0;
}
Version info: g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
回答1:
A common way to implement virtual functions is to have a pointer to a "virtual table" or vtable at a negative offset from the object. This table is needed to figure out what virtual function to call. This is why just malloc'ing space doesn't work.
回答2:
malloc
only allocates memory, but does not create an object. So, the line
Aa* aa = (Aa*)malloc(sizeof(Aa));
allocates a region of memory that is large enough to hold an A
, but contains garbage. As others pointed out, this also means that the pointer to the vtable
will not be set (I got that one from @David Rodríguez's comment on another answer), which is required to dispatch calls to virtual functions. Since B
does not contain virtual functions, no such problem arises. It would happen with B
too, however, if B
contained any data-members that require initialization, such as this:
class B
{
public:
B() : foo(new int()) {}
int f() {return *foo;}
private:
int * foo;
};
The line
Aa* aan = (Aa*)new Aa();
can do without the cast:
Aa* aan = new Aa();
回答3:
The reason is that malloc
knows nothing about C++ constuctors and consequently does not call them. You can call the constuctors yourself using placement new:
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
new(aa)Aa;
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
new(bb)Bb;
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
aa->~Aa();
free(aa);
delete aan;
bb->~Bb();
free(bb);
return 0;
}
Note that you have to manually call the destructors before freeing such memory.
回答4:
Don't use malloc, use new - malloc does not call constructors.
When you do A * a = new A();
the compiler will allocate memory, set up the vtable pointer for A and call the constructor. When you call a virtual function, the vtable is used to actually find the function.
When you do A * a = (A *) malloc(...);
the compiler will allocate memory, which will contain random data. When you call a virtual function, it'll look at the (garbage) vtable and call some random location.
A class with virtual functions look something like this internally:
struct Foo {
void * vtable;
int aClassMemberVar;
};
Calling a virtual function looks at the "hidden" vtable pointer, which points to the class vtable, a linked list of pointers to functions. So this vtable pointer must be initialized, and malloc doesn't do that.
回答5:
Surely because the Virtual Function Table isn't getting created properly?
回答6:
malloc
does not call the constructor of the class, so your object is not initailized properly, hence it seg faults. Use new
to allocate memory when using C++. BTW, there is no need to cast the pointer returned from new
.
回答7:
The good reason is called virtual tables. Objects of types that have virtual methods have a table of pointers pointing to the address of the actual virtual methods to be called. These are called virtual tables or v-tables.
来源:https://stackoverflow.com/questions/5311548/whats-the-issue-with-malloc-and-virtual-functions