peo*_*oro 6 c++ memory malloc alignment new-operator
我有这个琐碎的类层次结构:
class Base {
public:
virtual int x( ) const = 0;
};
class Derived : public Base {
int _x;
public:
Derived( int x ) : _x(x) { }
int x( ) const { return _x; }
};
Run Code Online (Sandbox Code Playgroud)
如果我malloc用来分配一个实例Derived,然后尝试访问多态函数x,程序崩溃(我得到一个分段错误):
int main( ) {
Derived *d;
d = (Derived*) malloc( sizeof(Derived) );
*d = Derived( 123 );
std::cout << d->x() << std::endl; // crash
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然我的实际应用程序要复杂得多(它是一种内存池).
我很确定这是因为我分配的方式d:我没有使用new.
我知道贴片new操作符,这必须是我需要的,但我从来没有使用它并且有一些问题:
为什么我的应用程序崩溃,如果我不使用new?
什么是new真正做到?
为什么我不能只使用赋值运算符来指定由Derived( 123 );指向的内存区域的值d?
我还需要new用于非多态类型吗?
POD怎么样?
在我上面链接的C++ Faq中,它表示传递给placement的内存区域new必须与我正在创建的对象对齐.
我知道对齐是什么,但我不知道如何检查我班级所需的对齐方式.
malloc 手册说:
malloc()和calloc()函数返回一个指向已分配内存的指针,该内存适合于任何类型的变量.
我希望我的类所需的对齐是返回的类大小sizeof,以便表单中的任何地址address_returned_by_malloc + i * sizeof(my_class)都适合分配我的对象.
我的希望是对的吗?
让我们顺着线往下走
虚拟表已损坏。
虚拟表卡在分配的内存之后。当您new创建一个类时,生成的代码将正确设置 vtable。但是,malloc 不会正确初始化 vtable
要查看虚拟表,请运行 g++ -fdump-class-hierarchy
Vtable for Derived
Derived::_ZTV7Derived: 3u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI7Derived)
16 Derived::x
Class Derived
size=16 align=8
base size=12 base align=8
Derived (0x10209fc40) 0
vptr=((& Derived::_ZTV7Derived) + 16u) <-- notice how this is part of the structure
Base (0x10209fcb0) 0 nearly-empty
primary-for Derived (0x10209fc40)
Run Code Online (Sandbox Code Playgroud)
出于类似的原因,在不重载operator=的情况下,生成的汇编代码将只复制数据而不复制vtable[再次强调,编译器只知道复制数据,而不知道复制vtable]
如果您想查看具有有效 vtable 函数的基于指针的版本:
Derived e(123);
d = &e;
Run Code Online (Sandbox Code Playgroud)
如果您使用的是虚函数,那么是的,即使对于非多态类型也是如此
对齐不是问题。