问题
I have some confusion about these three concepts: Stack, Heap, and Dynamic memory allocation. I'll provide examples in C++.
Am I correct to say that given a program, for all its variables, arrays, and maybe objects on stack, when the program just starting, all the memory space needed is already there, so everything is predetermined? But when the program is running, for me it still sounds like "dynamic" since a stack is still changing in a sense that values are still push into, pop off the stack, on the runtime.
Regarding to heap, for the "dynamic" sense, I brought the idea from some answer on this site, it's for something determined on runtime:
cin >> box_size; int *box = new int[box_size];
But, then how about this†:
Box surprise_box = new Box();
I already know how much space it's needed on compile time right? But it's still on the heap. So it seems like "Dynamic" memory allocation is just about the burden of allocation/deallocation of memory becomes one of programmer's.
†: It should be Box *ptr_surprise_box = new Box();
instead. (Thanks for the comment)
I understand why my question is considered too broad, but I don't know how to split them into pieces. Even worse, now I'm considering whether this has something to do with address space and those memory address determined in compile time.
回答1:
- Generally speaking, yes. At the beginning of your program, most of the data is on stack when you call a function, then you can allocate memory on heap. (Well, there is not only
stack
orheap
in a program, there may be also global variables in other segments, it is a long story).
The stack space is allocated by compiler, when you enter a function, the compiler generated code allocates enough space for the stack variables automatically.
The heap space is allocated by you, when you need some memory, you call a function to allocate heap space for you.
- The pointer to an address of memory is a variable on stack
For your code:
cin >> box_size;
int *box = new int[box_size];
Here box
is a variable on stack. The value of box
variable is a pointer to the memory on heap.
But Box surprise_box = new Box();
is not valid syntax.
Examples:
Box box1;
: the variablebox1
is on stack.Box *box2 = new Box();
: the variable ofbox2
is on stack, it is a pointer, points to the memory ofnew Box()
Updated:
There is no clear "dynamic" definition with "heap" and "stack" concept. For example, in C99, if you do scanf("%d", &size); int a[size]
; it is still OK and a
can be on stack, not heap. It all depends on the compiler's behavior. Memory allocated by you is usually on heap (you called memory allocation functions, including new()
), memory allocated by the compiler's code is usually on stack.
ps: I think @Slava's answer is quite good. These conepts are in different fields. stack
and heap
are mainly OS-related, dynamic
and static
are mainly language-related. I just talked about the most implementations of the modern C++ language, they happened to put new()
memory into heap, etc.
回答2:
I have some confusion about these three concepts: Stack, Heap, and Dynamic memory allocation.
Of course you are, you mixed concepts from different area - first 2 are related to OS, last on to the language.
For C++ there is no such thing as stack or heap. There are 4 different storage durations for objects in C++: automatic, static, thread and dynamic. Yes objects with automatic storage duration are usually stored in stack and ones with dynamic in heap, but that is details of implementations - from language point of view there are no such things. Details about storage duration can be found here
回答3:
I find that best way to look at heap vs. stack, is not in terms of "dynamic" or "knowing the size at compile time", (though, those can be factors). Instead, it is best to view them in terms of lifetime management.
Things allocated on the stack are destroyed when they go out of scope. Things allocated on the heap will exist until they are explicitly freed with a delete
, free
, or delete[]
(depending on how they are allocated).
To answer your questions:
Am I correct to say that given a program, for all its variables, arrays, and maybe objects on stack, when the program just starting, all the memory space needed is already there, so everything is predetermined.
Eh, on a per-function basis, kinda..., but this view doesn't really account for the fact that functions can do things like calling themselves (recursion) and reach arbitrary stack size usage.
So it seems like "Dynamic" memory allocation is just about the burden of allocation/deallocation of memory becomes one of programmer's.
Yes, the fundamental difference is really all about lifetime management.
回答4:
User slava had mentioned these:
automatic
,static
,thread
anddynamic
I will focus on all but thread
. He also stated this:
For C++ there is no such thing as stack or heap
User Even Teran had stated this:
I find that best way to look at heap vs. stack, is not in terms of "dynamic" or "knowing the size at compile time", (though, those can be factors). Instead, it is best to view them in terms of lifetime management.
Things allocated on the stack are destroyed when they go out of scope. Things allocated on the heap will exist until they are explicitly freed with a delete, free, or delete[] (depending on how they are allocated).
I will combine the two previous answers into a single answer with demonstrations:
- 1st -
Automatic Storage
int main () {
int x = 5;
{ // new scope
int x = 7;
std::cout << x << '\n'; // prints 7
} // end scope
std::cout << x << '\n'; // prints 5
return 0;
}
This is considered Automatic Storage
since the variable declarations and memory are destroyed once they go out of scope. You can consider this a stack
variable in a sense since in C++ each function
has a stack frame
. These variables x
above both live within main.cpp
's stack frame but have automatic storage
. However the first call to std::cout
will print 7
since it is within the same scope of the 2nd variable declared x
. Once the closing
brace }
is reached this scope is destroyed and so is the 2ndx
variable. So when we reach the next call to std::cout
this will print 5
because it is within the same scope of the 1st declared x
.
- 2nd -
Dynamic Storage
int main() {
int x = 5; // Automatic storage
int* ptr = nullptr; // raw pointer
ptr = new int(x); // Dynamic Storage
std::cout << "x = " << x << '\n'; // prints 5
std::cout << "*ptr = " << *ptr << '\n'; // prints 5
{ // new scope
*ptr = 12;
} // end scope
std::cout << "x = " << x << '\n'; // x unchanged prints 5
std::cout << "*ptr = " << *ptr << '\n'; // prints 12
delete ptr; // clean up memory
return 0;
}
Dynamic Storage
lives longer than the scope it is declared in. You can pass dynamic memory from one function to another as long as the original object that it references is still valid otherwise you will have a memory leak, invalid or dangling pointer which can lead the unwanted behavior, undefined behavior, program crash, your OS erased and nuclear bombs going off! (Well the last is a bit dramatic; but don't laugh because poor memory management will reek havoc on your code base and ALL WHO use it!). This allows you to store data and to modify it from one function to another without having to create copies upon copies of it every time you need to reference it in some other calculation.
- 3rd -
Static Storage
static int i = 0; // static storage: life time of application or file scope; similar to a global...
void add1() {
i++;
}
int main() {
std::cout << i << '\n';
add1();
std::cout << i << '\n';
for ( int n = 0; n < 10; n++ ) {
add1();
std::cout << "n=" << n << ": " << i << '\n';
}
return 0;
}
Output
0
1
n=0: 2
n=1: 3
n=2: 4
n=3: 5
n=4: 6
n=5: 7
n=6: 8
n=7: 9
n=8: 10
n=9: 11
Static Storage
is a little different. There is no need to clean it up like dynamic memory since it has properties similar to Automatic Storage
as it will be destroyed automatically. However, these are typically seen in global namespace
or global file space
they can be useful, but global variables again can be dangerous if not managed nor used properly. These typically have the lifetime of either the program application if defined in main.cpp
or the lifetime of file-scope if defined in some other cpp file. The only other difference with Static Storage
is it is also only initialized once, and there is usually only ever one instance of it!
Yes there are different types of storage classes and many still refer to them as stack
and heap
mainly cause C++
was built off of C
; but the meanings and usages have change dramatically over the years. Anymore in C++
it has more to do with the lifetime and visibility of a variable than where
it is located in memory.
来源:https://stackoverflow.com/questions/53808955/stack-heap-and-dynamic-memory-allocation