简体   繁体   中英

Coalescing two memory chunks in C++?

I'm trying to make my own memory allocator in C++ for educational purposes, and I have a code like this:

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;
};

And I'm stuck with how to have unused memory chunks merge. I'm trying to test it like this:

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;

The output is 8 as expected. My questions:

  • Why the output is correct?
  • Is the code like this correct? If not, are there any other ways to implement coalescence of two memory chunks?

UPDATE: All methods work correctly. eg this would work:

ss->setVar(54);
cout << ss->getVar();

The output is 54.

UPDATE 2: First of all, my task is not to request a new memory block from OS for instantiating an object, but to give it from a linked list of free blocks(that were allocated when starting a program). My problem is that I can have polymorphic objects with different sizes, and don't know how to split memory blocks, or merge (that is what I understand by merging or coalescing chunks) them (if allocation is requested) effectively.

There's a number of misunderstandings apparent here

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 is a pointer that is pointing to only a single char* , which is the variable pz2 . Meaning that any access or modification past pzz[0] is undefined behavior (very bad). You're likely modifying the contents of some other variable.

new (&pzz) IntObj; // questionable

This is constructing an IntObj in the space of the variable pzz , not where pzz is pointing to. The constructor of course sets a to 8 thereby stomping on the contents of pzz (it won't be pointing to pz2 anymore). I'm uncertain if this in-and-of-itself is undefined behavior (since there would be room for a whole IntObj ), but using it certainly is:

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

This violates the strict-aliasing rule. While the standard is generous for char* aliases, it does not allow char** to IntObj* aliases. This exhibits more undefined behavior.

If your question comes down to whether or not you can use two independent and contiguous blocks of memory as a single block then no, you cannot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM