Appleshell
Appleshell

Reputation: 7388

Handling allocated and stack memory

I provide two ways to add elements to my collection, once per const reference and once per pointer.

void push_back(const value_type *val) {
    element *elem = new element(val);
    //...
}
void push_back(const value_type &val) {
    push_back(&val);
}

The element class holds the value as a pointer.

class element {
private:
    const value_type *value;
public:
    element(const value_type *value):
    value(value) {
    } 

    ~element() {
        delete value;
    }

Obviously when elements are popped or the collection is deleted, the memory has to be freed if elements were added as a pointer. However, this yields an error when the elements were not manually allocated and passed by reference.

Is there any other option to solve this issue than additionally storing if the element is dynamically allocated on push_back time?

Upvotes: 0

Views: 110

Answers (2)

lapk
lapk

Reputation: 3918

It's a flawed design in general. And there are different ways you can change your design to achieve what you need. Mark's answer is a straightforward way to go about it, for example.

That being said, here is a possible solution using your design. Once again, I do not recommend it as it relies on internals of how compilers build stack, and is not portable across compilers/platforms.

Basically, in ~element() you can check if the address stored in value is on stack or on heap by comparing it to the current stack pointer. If the address stored in value is higher than the stack pointer then it's on stack and should not be deleted (provided usual location of the stack at top of address space). If it's less than stack pointer - it's on heap.

Code to illustrate the relations of the addresses (GCC, x64 linux):

#include <iostream>

int main()
{
 int * heap_(new int(0));
 int stack_(0);
 void * rsp_(nullptr);

 asm("mov %%rsp, %0" : "=m" (rsp_));

 std::cout << "heap address\t: " << heap_ 
           << "\nstack address\t: " << &stack_ 
           << "\nstack pointer\t: " << rsp_ << std::endl;

 delete (heap_);

 return (0);
}

Program output:

heap address    : 0xc52010
stack address   : 0x7fff528ffee4
stack pointer   : 0x7fff528ffee0

ideone.com gives access to GCC, but uses x86 version - esp register instead of rsp. The code has to be changed (non-portability).

Upvotes: 1

Mark Ransom
Mark Ransom

Reputation: 308186

Just be consistent and always store a pointer that can be deleted.

void push_back(const value_type &val) {
    push_back(new value_type(val));
}

Upvotes: 1

Related Questions