我正在尝试用C ++创建自己的内存分配器用于教育目的,我有一个这样的代码:
class IntObj
{
public:
IntObj(): var_int(6) {}
void setVar(int var)
{
var_int = var;
}
int getVar()
{
return var_int;
}
virtual size_t getMemorySize()
{
return sizeof(*this);
}
int a = 8;
~IntObj()
{}
private:
int var_int;
};
我一直坚持如何将未使用的内存块合并。我试图像这样测试它:
char *pz = new char[sizeof(IntObj) * 2]; //In MacOS, IntObj takes 16 bytes
char *pz2 = &pz[sizeof(IntObj)]; // Take address of 16-th cell
char *pz3 = new char[sizeof(IntObj) / 2]; //Array of 8 bytes
char **pzz = &pz2;
pzz[sizeof(IntObj)] = pz3; // Set address of cell 16 to the pz3 array
new (&pzz) IntObj; //placement new
IntObj *ss = reinterpret_cast<IntObj *>(&pzz);
cout << ss->a;
输出为预期的8。我的问题:
更新:所有方法都正常工作。 例如,这将起作用:
ss->setVar(54);
cout << ss->getVar();
输出为54。
更新2:首先,我的任务不是从OS请求新的内存块来实例化对象,而是从空闲块的链接列表(在启动程序时分配)中提供它。我的问题是我可以拥有不同大小的多态对象,并且不知道如何有效地拆分内存块,或者合并(这是我通过合并或合并块理解的)它们(如果请求分配)。
答案 0 :(得分:3)
这里有许多误解
char *pz = new char[sizeof(IntObj) * 2]; // fine
char *pz2 = &pz[sizeof(IntObj)]; // fine
char *pz3 = new char[sizeof(IntObj) / 2]; // fine
char **pzz = &pz2; // fine
pzz[sizeof(IntObj)] = pz3; // bad
pzz
是一个指针,只指向一个char*
,即变量pz2
。意味着过去pzz[0]
之后的任何访问或修改都是未定义的行为(非常糟糕)。您可能正在修改其他变量的内容。
new (&pzz) IntObj; // questionable
这是在变量 IntObj
的空间中构建pzz
,而不是pzz
所指向的位置。当然,构造函数将a
设置为8
,从而踩踏pzz
的内容(它不再指向pz2
)。我不确定这个本身是否是未定义的行为(因为整个IntObj
都有空间),但使用它肯定是:
IntObj *ss = reinterpret_cast<IntObj *>(&pzz); // bad
这违反了严格别名规则。虽然该标准对于char*
别名是慷慨的,但不允许char**
到IntObj*
别名。这表现出更多未定义的行为。
如果您的问题归结为您是否可以将两个独立且连续的内存块用作单个块,那么不可以。