简体   繁体   中英

Why would you use the stack if there is a possibility of stack overflow

Let's say I have a class that repsents my application: (sorry for not showing both h and cpp but this is for brevity)

class App
{
    App()
    {
        window( new Window() );
        window->Height( 400 );
        window->Width( 400 );
        window->Title( "Bob" );
    }

    unique_ptr<Window> window;
    // ... Possibly more variables
}

class Window
{
public:

    // Get
    int Height(){ ... };
    int Width(){ ... };
    string Title(){ ... };    

    // Set
    void Height( int height ){ ... };
    void Width( int width ){ ... };
    void Title( string title ){ ... };

private:

    int height;
    int width;
    string title;

    // ... Possibly more variables

}

App app;

int main()
{

}

All of the int and string types inside my Window class are declared on the stack. At some point, I'm going to end up with a stack overflow if I keep declaring stuff on the stack inside these classes... right?

So my question is ... Why would you ever want to declare stuff on the stack? shouldn't we I just be doing this instead?

// ...
App()
{
    window( new Window() );
    window->Height( unique_ptr<int>( new int( 400 ) ) );
    window->Width( unique_ptr<int>( new int( 400 ) ));
    window->Title( unique_ptr<string>( new string( "Bob" ) ) );
}
// ...
private:

    unique_ptr<int> height;
    unique_ptr<int> width;
    unique_ptr<string> title;

...

The difference being that the memory for the integers and strings are now declared on the heap.

Why would you ever want to declare stuff on the stack?

2 reasons I can think of:

  1. Performance: The stack is extremely fast. I remember hearing this somewhere but the best way to improve performance is to avoid a trip to the heap.

  2. Complexity: Using dynamic memory creates more complexity as you have to think about memory management. Using the stack keeps it much more simple than using the heap. Using dynamic memory increases the complexity of your program.

Even when you declare window as unique_ptr<Window> window you are declaring something on the stack. In this case an instance of unique_ptr<Window> . It is fine to declare ints and other small primitives or structs on the stack because even if you declare them on the heap you will need to declare the pointer to them on the stack. You will always need to hold a pointer to the location on the heap, in the stack so if your data type is smaller than a pointer (or close to the same size) than it is even more efficient to hold it on the stack rather than the heap. This is because it is quicker to access the stack than the heap, and memory wise you have to store two objects when storing on the heap (the pointer and the object itself) and only one when storing on the stack.

Take std::string for instance. It probably holds internally a pointer to a location on the heap where the raw data is stored. So on the stack you are holding a pointer and on the heap the raw data (string literals are a bit different put the general idea remains).

In general there is little point in storing an int in a unique_ptr unless it is the address of an array. It is more efficient and easier to maintain if you just declare it as a raw int.

You are prematurely worrying about optimizing stack usage.

You indicated C++.

For C++ on Linux, the default stack size for ubuntu 12.04 and 15.04 is 8 MegaBytes.

The sizeof() Height and Width are 4 bytes each.

If you are using std::string, and gcc 4.9 on Ubuntu 15.04, the sizeof(an_empty_std_string_object) is 8 bytes (on the stack)

Additionally the sizeof(a_100_char_string_object) is only 8 bytes. I would guess that std::string is a simple wrapper around dynamic memory, but I have never checked.

So an 8 MByte stack will hold more than 10^6 of your 16 byte objects. Maybe you could fill this stack using recursion.


Imagine you move all 16 bytes of your object to the heap (ie you new your object to the heap)

You would still use 8 bytes (on 64 byte linux) on the stack to point to your object.

I have not looked at how big a smart pointer is, but it will probably be 16 bytes, not sure yet.


Perhaps you are worried enough to put each of your objects into a vector. An empty vector is 24 bytes, and so is a 1000 element vector, and so is a 1 Million Element vector, ...

Anyway, if you are nearing stack limits (it is doable, I've done it with recursive algorithms), in Linux you can change the stack size ... I have tried a 1 GByte stack ... just to see how far that recursive program would get. Not that much further. (Sorry, I did not finish that experiment.)


All of the int and string types inside my Window class are declared on the stack.

No, not really. Your int and string types are declared as data attributes of your class instances. If your class instances are instantiated on the heap (ie using new), then that data will be in the heap, not on the stack.

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