C ++:为什么`new`需要的? [英] C++: why is `new` needed?

查看:154
本文介绍了C ++:为什么`new`需要的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的类层次结构:

 类基地{
上市:
    虚拟INT X()常量= 0;
};

类派生的:公共基础{
    INT _x;
上市:
    派生(INT X):_x(X){}
    INT X()const的{返回_x; }
};
 

如果我用的malloc 分配的衍生的实例,然后尝试访问该多态函数 X ,程序崩溃(我得到一个分段错误):

  INT主要(){
    衍生* D;
    D =(导出*)malloc的(的sizeof(衍生));
    * D =派生(123);

    性病::法院<<的d-&X的催化剂()&其中;&其中;的std :: ENDL; //崩溃

    返回0;
}
 

当然,我的实际应用是一个复杂得多(这是一个类型的内存池)。


我是pretty的肯定这是因为我分配的方式 D :我没有使用

我知道安置 运营商,它必须是我所需要的,但我从来没有使用过它,并得到了一些问题:

  • 为什么我的应用程序崩溃,如果我不使用

    这是什么实际上做?

    为什么我不能只使用赋值运算符来分配的(123)的值而得; 来指出由 D <存储区域/ code>?

  • 请问我需要使用也非多态类型?

    如何POD的?

  • C ++ FAQ我联系上面该说,存储区域传递到安置必须对准了我创建的对象。

    我知道对齐是什么,但我不知道如何检查需要我的课的定位。

    的malloc 手册说:

      

    的malloc()和释放calloc()函数返回一个指针适合任何类型的变量排列分配的内存。

    我希望,需要我的课的定位是作为sizeof的返回的班级规模,使之在形式的任何地址 address_returned_by_malloc + I *的sizeof(my_class)适用于分配我的对象。

    是我的希望吧?

解决方案

让我们下去就行

  1. 为什么我的应用程序崩溃,如果我不使用新的?

虚拟表已损坏。

虚拟表所分配的内存之后卡住。当你一类,所产生的code将正确设置虚函数表。不过,malloc的不正确初始化虚函数表

要看到虚拟表,跑     G ++ -fdump类层次结构

  V表的派生
衍生:: _ ZTV7Derived:3U项
0(中间体(*)(...))0
8(中间体(*)(...))(&安培; _ZTI7Derived)
16派生:: X

派生类
   大小= 16 ALIGN = 8
   底座尺寸= 12基地ALIGN = 8
派生(0x10209fc40)0
    的vptr =((&安培;衍生:: _ ZTV7Derived)+ 16U)所述;  - 注意这是怎么结构的一部分
  基地(0x10209fcb0)0近空
      初级的衍生(0x10209fc40)
 

出于同样的理由,没有超载运算符=,生成的程序集code时,只复制数据,而不是虚函数表[再次,编译器只知道复制数据,而不是虚函数表]

如果你想看到一个基于指针的版本有一个有效的虚函数表的功能:

 派生E(123);
D =与评估;
 

  1. 在我需要使用新的也非多态类型?

如果您使用的是虚函数,那么,即使对于非多态类型

  1. 我希望,需要我的课的定位是为返回sizeof的班级规模,使之在形式address_returned_by_malloc + I *的sizeof(my_class)任何地址,适用于分配我的对象。

对齐是不是一个问题。

I've got this trivial class hierarchy:

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; }
};

If I use malloc to allocate an instance of Derived, and then try to access the polymorphic function x, program crashes (I get a segmentation fault):

int main( ) {
    Derived *d;
    d = (Derived*) malloc( sizeof(Derived) );
    *d = Derived( 123 );

    std::cout << d->x() << std::endl; // crash

    return 0;
}

Of course my actual application is a lot more complex (it's a sort of memory pool).


I'm pretty sure it's because of the way I allocate d: I didn't use new.

I know of placement new operator, which must be what I need, but I've never used it and have got some questions:

  • why is my application crashing, if I don't use new?

    What does new actually do?

    Why can't I just use the assignment operator to assign the value of Derived( 123 ); to the memory area pointed by d?

  • Would I need to use new also for non-polymorphic types?

    How about POD ones?

  • On the C++Faq I linked above it says that the memory region passed to placement new must be aligned for the object I'm creating.

    I know what alignment is, but I don't know how to check the alignment needed for my class.

    malloc manual says:

    The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable.

    And I hope that the alignment needed for my class is the class size as returned by sizeof, so that any address in the form address_returned_by_malloc + i * sizeof(my_class) is suitable to allocate my objects.

    Are my hopes right?

解决方案

Let's go down the line

  1. why is my application crashing, if I don't use new?

Virtual table is corrupted.

The virtual table is stuck right after the allocated memory. when you new a class, the generated code will properly set up the vtable. However, malloc will not properly initialize the vtable

To see the virtual table, run 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)

For a similar reason, without overloading operator=, the generated assembly code will only copy the data and not the vtable [again, the compiler only knows to copy the data, not the vtable]

If you want to see a pointer-based version with a valid vtable function:

Derived e(123);
d = &e;

  1. Would I need to use new also for non-polymorphic types?

If you are using virtual functions, then yes, even for non-polymorphic types

  1. I hope that the alignment needed for my class is the class size as returned by sizeof, so that any address in the form address_returned_by_malloc + i * sizeof(my_class) is suitable to allocate my objects.

Alignment is not an issue.

这篇关于C ++:为什么`new`需要的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆