0

我正在尝试在 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:首先,我的任务不是从操作系统请求一个新的内存块来实例化一个对象,而是从一个空闲块的链接列表(在启动程序时分配)中提供它。我的问题是我可以拥有不同大小的多态对象,并且不知道如何拆分内存块,或者有效地合并(我通过合并或合并块来理解)它们(如果请求分配)。

4

1 回答 1

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的空间中构造一个,而不是指向的地方。构造函数当然会设置为(它不会再指向)的内容。我不确定这本身是否是未定义的行为(因为会有整体的空间),但使用它肯定是: pzzpzza8pzzpz2IntObj

IntObj *ss = reinterpret_cast<IntObj *>(&pzz); // bad

这违反了严格的混叠规则。虽然该标准对别名很慷慨,char*但它不允许别名。这表现出更多未定义的行为。char**IntObj*

如果您的问题归结为您是否可以将两个独立且连续的内存块用作单个块,那么不,您不能。

于 2018-06-10T10:36:00.373 回答