【问题标题】:On VTable pointers and malloc关于 VTable 指针和 malloc
【发布时间】:2011-12-03 21:44:02
【问题描述】:

是否有任何独立于编译器且语法优雅的方法来在使用 malloc 分配的对象中设置 vtable 指针?

我不能直接使用 new,因为我需要能够按需控制内存释放的流程,这需要使用 void ptrs 在内存管理器中保存内存位置,直到有足够的时间释放。

class AbstractData
{
public:
   AbstractData() {}
   virtual ~AbstractData() {}

protected:
   virtual void SetData(int NewData) =0;
   virtual int GetData() const =0;
};

class ConcreteData : public AbstractData
{
protected:
   int Data;

public:
   ConcreteData() {}
   ~ConcreteData() {}

   void SetData(int NewData);
   int GetData() const;

};

void ConcreteData::SetData(int NewData) {Data=NewData;}

int ConcreteData::GetData() const 
{return Data;}

int main(int argc, char* argv[])
{
    int OBJ_NUMBER = 4;
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData));

    if (!Test)
        return -1;        

    for (int x = 0; x < OBJ_NUMBER; x++)
       Test[x] = ConcreteData();

    Test[0]->GetData(); //Constructor was never called, vptr never initialized, crash

    free(Test);
    Test = NULL;
}

我希望本地副本会有一个已初始化的 vtable 指针,但可惜它没有。 我知道如果你知道 vptr 在哪里,你可以对 vptr 的偏移量进行依赖于编译器的取消引用,但是这个解决方案依赖于编译器并且不适合在许多分配中使用。示例适用于 MSVC++ 8.0

int main(int argc, char* argv[])
{
    int OBJ_NUMBER = 4;
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData));

    if (!Test)
        return -1;        

    ConcreteData StealVPtr();

    int* VPtr = *(int**)StealVPtr; 

    for (int x = 0; x < OBJ_NUMBER; x++)
       *(int**)Test[x] = VPtr;

    Test[0]->GetData(); //VPtr initialized in compiler dependent way

    free(Test);
    Test = NULL;
}

或者,也可以使用放置 new,但它再次看起来在语法上不优雅,并且当它在 ptr 前面添加数组计数时,可能会导致带有析构函数的类型的数组偏移问题。

int main(int argc, char* argv[])
{
    int OBJ_NUMBER = 4;
    ConcreteData* Test = (ConcreteData*)malloc(OBJ_NUMBER*sizeof(ConcreteData));

    if (!Test)
        return -1;        

    for (int x = 0; x < OBJ_NUMBER; x++)
    {
        if (!(ConcreteData* PlcTest = new(Test[x]) ConcreteData()))
        {
           free(Test);
           Test = NULL;
           return -1;
        }
    }

    PlcTest[0]->GetData(); //Constructor was invoked and VPtr was initialized

    for (int x = OBJ_NUMBER-1; x >= 0; x--)
        PlcTest[x].~ConcreteData();

    PlcTest = NULL;

    free(Test);
    Test = NULL;
}

这些真的是使用 malloc 在对象上初始化 VTable ptr/call 构造函数的唯一方法吗?

【问题讨论】:

  • 新听起来是个不错的选择。或许您需要重新审视一下是什么导致您采用这种策略。
  • 这一定是说“WTF??!?”的最好和最礼貌的方式。注意以备将来使用!
  • 标记c? C没有new、class、public、virtual、protected、构造函数或析构函数的概念; malloc, ..., ...的返回值不需要强制转换

标签: c++ memory-management malloc vtable


【解决方案1】:

您可能不知道可以覆盖全局newdelete。注意,还需要覆盖new[]delete[]才算完整

这里是一个例子:

void * operator new( size_t size ) 
{
    return super_malloc( size );
}

【讨论】:

    【解决方案2】:

    您可以使用placement new operator 在预分配内存中构造类实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2018-02-10
      • 2016-07-05
      相关资源
      最近更新 更多