Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Convert beween Stack and Heap Objects

Example:

Class *_obj1;
Class *_obj2;

void doThis(Class *obj) {}

void create() {
    Class *obj1 = new Class();
    Class obj2;

    doThis(obj1);
    doThis(&obj2);

    _obj1 = obj1;
    _obj2 = &obj2;
}

int main (int argc, const char * argv[]) {

    create();

    _obj1->doSomething();
    _obj2->doSomething();

    return 0;
}

This creates 2 objects, creates pointers to them, then main() calls a method on each. The Class object creates a char* and stores the C string "Hello!" in it; the ~Class() deallocator frees the memory. The doSomething() method prints out "buff: %s" using printf(). Simple enough. Now if we run it we get this:

Dealloc
Buff: Hello!
Buff: ¯ø_ˇ

Obviously the stack object does not work here - it's obvious that when the function exits the pointer _obj2 is pointing at a location in the stack. This is why I used heap objects in my previous question, which people told me was "stupid".

So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer, not an arrogant "you're doing it wrong" as so many have done. Because in this case stack objects cannot work so heap objects seem to be the only way. EDIT: Also, converting back to a stack object would be useful as well.

The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap. So what's the right way to do it?

like image 658
Justin Mrkva Avatar asked Feb 20 '11 17:02

Justin Mrkva


People also ask

What is difference between stack and heap?

Heap memory is used by all the parts of the application whereas stack memory is used only by one thread of execution. Whenever an object is created, it's always stored in the Heap space and stack memory contains the reference to it.

Can the stack and heap run into each other?

If the stack grows into the heap, the typically C compiler will silently start to overwrite the heap's data structures. On a modern OS, there will be one or more virtual memory guard pages which prevent the stack from growing indefinitely.

Which is faster heap or stack?

The stack is faster because the access pattern makes it trivial to allocate and deallocate memory from it (a pointer/integer is simply incremented or decremented), while the heap has much more complex bookkeeping involved in an allocation or free.

Why do we use heap instead of stack?

Stack memory allocation is considered safer as compared to heap memory allocation because the data stored can only be access by owner thread. Memory allocation and de-allocation is faster as compared to Heap-memory allocation. Stack-memory has less storage space as compared to Heap-memory.


2 Answers

So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits? I want a straight answer,

The straight answer is: You can't "convert" an object between the stack and heap. You can create a copy of the object that lives in the other space, as others have pointed out, but that's it.

The second question: the specific example of heap objects being "wrong" was creating a new vector* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way? Obviously if you create them as stack objects it fails because they're immediately deallocated, but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.

Dynamically allocating STL objects will not on its own corrupt the heap. (No idea where you might have heard that.)

If you want to use a stack-allocated STL object outside of the function that you created it in, you can't, since the stack space in which the object resides is only valid inside the function that created it.

You can, however, return a copy of the object:

std::vector<char> SomeFunc()
{
    std::vector<char> myvector;
    // myvector.operations ...
    return myvector;
}

As I said, though, this will return a copy of the object, not the original object itself -- that would be impossible, since the stack that contains the object is unwound after the function returns.

One other option is to have the caller pass in a reference / pointer to the object that your function manipulates, if this makes sense for your particular scenario:

void SomeFunc(std::vector<char>& destination)
{
    // destination.operations ...
}

void AnotherFunc()
{
    std::vector<char> myvector;
    SomeFunc(myvector);
}

As you can see, you've still allocated everything on the stack, and you avoid the (sometimes consequential) overhead of relying on the copy-constructor to return a copy of the object.

like image 110
Ben M Avatar answered Sep 20 '22 21:09

Ben M


So, the first question is: if how can I convert the stack object (obj2) to a heap object so it's not deallocated after create() exits?

This line:

_obj2 = &obj2;

Change to:

_obj2 = new Class(obj2);  // Create an object on the heap invoking the copy constructor.

I want a straight answer, not an arrogant "you're doing it wrong" as so many have done.

Thats as straight an answer as you can get. Obviously you are new to C++, So I am sure this will nto work as intended because you have probably made a couple of mistakes in the defintion of the class "Class" (by the way terrible name).

Also, converting back to a stack object would be useful as well.

class obj3(*_obj2);  // dereference the heap object pass it to the copy constructor.

The second question: the specific example of heap objects being "wrong" was creating a new vector<string>* using the new operator. If dynamically allocating STL objects is wrong, then what's the right way?

Why do you dynamically allocate the vector. Just create it locally.

std::vector<std::string> funct()
{
    std::vector<std::string>   vecString;
    // fill your vector here.

    return vecString;  // Notice no dynamic allocation with new,
}

Using new/delete is using C++ like C. What you need to read up on is smart pointers. These are obejcts that control the lifespan of the object and automatically delete the object when they go out of scope.

std::auto_ptr<Class>   x(new Class);

Here x is a smart pointer (of type auto_ptr) when it goes out of scope the object will be deleted. But you can return an auto_ptr to the calling function and it will be safely transfered out of the function. Its actually a lot more complicated than that and you need a book.

Obviously if you create them as stack objects it fails because they're immediately deallocated,

Its de'allocated when it goes out of scope.

but I've been told (again, by a very high-ranking member) that dynamically allocating them can corrupt the heap.

If you do it incorrectly. Which given your knowledge is very likely. But hard to verify since you have not provided the definition of Class.

So what's the right way to do it?

  1. Learn why you should use stack objects
  2. Learn what smart pointers are.
  3. Learn how to use smart pointers to control lifespans of objects.
  4. Learn the different types of smart pointers.
  5. Look up what the separation of concerns is (you are not following this basic principle).
like image 20
Martin York Avatar answered Sep 20 '22 21:09

Martin York