q0987
q0987

Reputation: 35982

Customized memory allocation and deletion

struct Rational
{
    int a;
    int b;
};

struct NextOnFreeList
{
    NextOnFreeList *next;
};

// Build the linked-list
NextOnFreeList* freeList = NULL; // head of the linked-list
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ? sizeof(Rational) : sizeof(NextOnFreeList *);
NextOnFreeList *runner = static_cast <NextOnFreeList *> new char [size]; // LineA
freeList = runner;
for (int i = 0; i < EXPANSION_SIZE; i++) {
    runner->next = static_cast <NextOnFreeList *> new char [size];
    runner = runner->next;
}
runner->next = 0;

Question 1> LineA Since the size of Rational(i.e. 8 bytes) is larger than NextOnFreeList(i.e. 4 bytes), each element in the Linked-list will ONLY use partial of the allocated memory. Is that correct?

// Delete the linked-list

NextOnFreeList *nextPtr = NULL;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
    freeList = freeList->next;
    delete [] nextPtr; // LineB
}

Question 2> LineB why should we use 'delete [] nextPtr' instead of 'delete nextPtr'?

Question 3>

Rational* ptr = static_cast<Rational*>( freeList ); // LineC
ptr->a = 10;
ptr->b = 20;

Is it true by LineC, we can bring back all the allocated memory original with size of 'size' and use the memory to store all elements inside the Rational.

Upvotes: 0

Views: 102

Answers (3)

firda
firda

Reputation: 3338

Q1: Yes, but I would rather use std::allocator<Rational>::allocate (or union of both - you will avoid alignment problems this way)

Q2: It is actually bad, because you should cast it to char* first, then use delete[]. Again, using std::allocator would be better. And: It does not matter on default implementation (calls free), but forget I said that ;) ... using malloc/free directly is safer.

Q3:: It is fine, but I am not sure if static_cast will allow that (reinterpret_cast or casting to void* in between may help)

EDIT: I hope your Q3 is not final, because you need to update the free list first (before using the pointer).

2nd EDIT: Links + note: hiding the free-list inside the allocator would be best for C++ (using malloc/free directly in it, or new[] / delete[])

Upvotes: 2

rahman
rahman

Reputation: 4948

Q.1:

Yes but that is not the best idea to use static_cast. reinterpret_cast would be more preferable.

Q.2: I dont there is a defined behavior to recognize your static_cast to accept a simple delete. safest way would be to look at this as the original allocation of array. So cast back to char* and use []delete

Q.3 yep, yes you can.

Upvotes: 0

Mark B
Mark B

Reputation: 96251

  1. That seems correct. In a 32 bit architecture you most likely overallocated and only a portion of the memory will be used. In a 64 bit architecture most likely the two sizes are the same.
  2. Neither one is appropriate. You allocated that memory as char* so you must delete it as such (by casting back to char* and then delete[]) or you have undefined behavior.
  3. Line C won't compile because the two pointee types are unrelated. If you did use reinterpret_cast you would be violating the strict aliasing rules, again causing undefined behavior.

Upvotes: 0

Related Questions