【发布时间】: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