【问题标题】:Allocating an array of Derived without new[]: Pointer to Base vtable is bad分配没有 new[] 的 Derived 数组:指向 Base vtable 的指针不好
【发布时间】:2011-01-03 21:48:06
【问题描述】:

基本上,我有一个纯虚拟类 Base,以及一个继承自 Base 的具体类 Derived。然后我分配一块内存并通过简单的转换将其视为 Derived 数组。然后,我使用 = 填充数组。最后,我循环遍历数组,尝试调用在 Base 中声明并在 Derived 中定义的虚方法 GetIndex。

问题是我最终得到一个访问冲突异常,试图读取指向 Base 的 vtable 的指针(在 Visual Studio 调试中,这显示为 __vfptr,它始终为 0xbaadf00d)。

以下是我遇到的问题的一个简单示例:

#include "stdafx.h"
#include "windows.h"

struct Base
{
    virtual int GetIndex() const = 0;
};

struct Derived : public Base
{
    int index;

    Derived()
    {
        static int test = 0;
        index = test++;
    }

    int GetIndex() const
    {
        return index;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    int count = 4;
    // Also fails with malloc
    Derived* pDerived = (Derived*)HeapAlloc(GetProcessHeap(), 0, sizeof(Derived) * count);

    for (int i = 0; i < count; i++)
    {
        Derived t;
        pDerived[i] = t;
    }

    // Should print 0 1 2 3
    for (int i = 0; i < count; i++)
    {
        Base& lc = pDerived[i];
        printf("%d\n", lc.GetIndex()); // FAIL!
    }
    return 0;
}

这种行为只发生在通过 HeapAlloc 或 malloc 分配内存时;如果使用 new[],它工作正常。 (另外,cstor之前被调用了4次,所以输出是4 5 6 7。)

【问题讨论】:

  • 作为参考,这是通过替换解决的:Derived t; pDerived[i] = t; with: new (&pDerived[i]) Derived();

标签: c++ inheritance dynamic-memory-allocation vtable


【解决方案1】:

如果您在没有new 的情况下分配内存,则始终需要使用placement new 手动调用构造函数,并使用x-&gt;~Derived(); 调用析构函数

【讨论】:

    【解决方案2】:

    我认为在第一个 for 循环中,您正在创建一个没有 new 的对象。这意味着这个对象的上下文是你的 for 循环。退出 for 循环后,此变量不再存在。

    【讨论】:

      【解决方案3】:

      如果你想使用 C++ 默认之外的分配器,你应该定义你自己的操作符 new 而不是每次都记住调用构造函数。

      void *operator new[]( size_t block_size, HANDLE heap ) {
          return HeapAlloc( heap, 0, block_size );
      }
      

      Derived *pDerived = new( GetProcessHeap() ) Derived[ count ];
      

      具体取决于你是否希望它成为分配Derived的默认方式以及它是否真的需要参数。

      如果free() 无法释放您获得的内存,您仍然需要小心。那么默认的delete 将不起作用,您应该创建Derived::operator delete 或编写自己的函数来调用object-&gt;~Derived()

      【讨论】:

        猜你喜欢
        • 2013-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-10
        • 2011-04-02
        • 1970-01-01
        相关资源
        最近更新 更多