Why would you ever want to allocate memory on the

2020-01-27 02:31发布

问题:

This question already has answers here:
Closed 10 years ago.

Possible Duplicate:
When is it best to use a Stack instead of a Heap and vice versa?

I've read a few of the other questions regarding the heap vs stack, but they seem to focus more on what the heap/stack do rather than why you would use them.

It seems to me that stack allocation would almost always be preferred since it is quicker (just moving the stack pointer vs looking for free space in the heap), and you don't have to manually free allocated memory when you're done using it. The only reason I can see for using heap allocation is if you wanted to create an object in a function and then use it outside that functions scope, since stack allocated memory is automatically unallocated after returning from the function.

Are there other reasons for using heap allocation instead of stack allocation that I am not aware of?

回答1:

There are a few reasons:

  • The main one is that with heap allocation, you have the most flexible control over the object's lifetime (from malloc/calloc to free);
  • Stack space is typically a more limited resource than heap space, at least in default configurations;
  • A failure to allocate heap space can be handled gracefully, whereas running out of stack space is often unrecoverable.

Without the flexible object lifetime, useful data structures such as binary trees and linked lists would be virtually impossible to write.



回答2:

  1. You want an allocation to live beyond a function invocation
  2. You want to conserve stack space (which is typically limited to a few MBs)
  3. You're working with re-locatable memory (Win16, databases, etc.), or want to recover from allocation failures.
  4. Variable length anything. You can fake around this, but your code will be really nasty.

The big one is #1. As soon as you get into any sort of concurrency or IPC #1 is everywhere. Even most non-trivial single threaded applications are tricky to devise without some heap allocation. That'd practically be faking a functional language in C/C++.



回答3:

So I want to make a string. I can make it on the heap or on the stack. Let's try both:

char *heap = malloc(14);
if(heap == NULL)
  {
    // bad things happened!
  }
strcat(heap, "Hello, world!");

And for the stack:

char stack[] = "Hello, world!";

So now I have these two strings in their respective places. Later, I want to make them longer:

char *tmp = realloc(heap, 20);
if(tmp == NULL)
  {
    // bad things happened!
  }
heap = tmp;
memmove(heap + 13, heap + 7);
memcpy(heap + 7, "cruel ", 6);

And for the stack:

// umm... What?

This is only one benefit, and others have mentioned other benefits, but this is a rather nice one. With the heap, we can at least try to make our allocated space larger. With the stack, we're stuck with what we have. If we want room to grow, we have to declare it all up front, and we all know how it stinks to see this:

char username[MAX_BUF_SIZE];


回答4:

The most obvious rationale for using the heap is when you call a function and need something of unknown length returned. Sometimes the caller may pass a memory block and size to the function, but at other times this is just impractical, especially if the returned stuff is complex (e.g. a collection of different objects with pointers flying around, etc.).



回答5:

Size limits are a huge dealbreaker in a lot of cases. The stack is usually measured in the low megabytes or even kilobytes (that's for everything on the stack), whereas all modern PCs allow you a few gigabytes of heap. So if you're going to be using a large amount of data, you absolutely need the heap.



回答6:

just to add you can use alloca to allocate memory on the stack, but again memory on the stack is limited and also the space exists only during the function execution only. that does not mean everything should be allocated on the heap. like all design decisions this is also somewhat difficult, a "judicious" combination of both should be used.



回答7:

Besides manual control of object's lifetime (which you mentioned), the other reasons for using heap would include:

  • Run-time control over object's size (both initial size and it's "later" size, during the program's execution).

For example, you can allocate an array of certain size, which is only known at run time.

With the introduction of VLA (Variable Length Arrays) in C99, it became possible to allocate arrays of fixed run-time size without using heap (this is basically a language-level implementation of 'alloca' functionality). However, in other cases you'd still need heap even in C99.

  • Run-time control over the total number of objects.

For example, when you build a binary tree stucture, you can't meaningfully allocate the nodes of the tree on the stack in advance. You have to use heap to allocated them "on demand".

  • Low-level technical considerations, as limited stack space (others already mentioned that).

When you need a large, say, I/O buffer, even for a short time (inside a single function) it makes more sense to request it from the heap instead of declaring a large automatic array.



回答8:

Stack variables (often called 'automatic variables') is best used for things you want to always be the same, and always be small.

int x;
char foo[32];

Are all stack allocations, These are fixed at compile time too.

The best reason for heap allocation is that you cant always know how much space you need. You often only know this once the program is running. You might have an idea of limits but you would only want to use the exact amount of space required.

If you had to read in a file that could be anything from 1k to 50mb, you would not do this:-

int readdata ( FILE * f ) {
  char inputdata[50*1024*1025];
  ...
  return x;
}

That would try to allocate 50mb on the stack, which would usually fail as the stack is usually limited to 256k anyway.



回答9:

The stack and heap share the same "open" memory space and will have to eventually come to a point where they meet, if you use the entire segment of memory. Keeping the balance between the space that each of them use will have amortized cost later for allocation and de-allocation of memory a smaller asymptotic value.