为什么要在堆而不是堆栈上分配内存?

发布于 2024-08-07 14:19:12 字数 440 浏览 5 评论 0原文

可能的重复:
什么时候最好使用堆栈而不是堆,反之亦然?

我已经阅读了一些有关堆与堆栈的其他问题,但他们似乎更关注堆/堆栈的作用而不是为什么你会使用它们。

在我看来,堆栈分配几乎总是首选,因为它更快(只需移动堆栈指针而不是在堆中寻找可用空间),并且在使用完毕后不必手动释放分配的内存。我认为使用堆分配的唯一原因是,如果您想在函数中创建一个对象,然后在该函数范围之外使用它,因为从函数返回后,堆栈分配的内存会自动取消分配。

使用堆分配而不是堆栈分配还有其他我不知道的原因吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

把梦留给海 2024-08-14 14:19:12

原因有几个:

  • 最主要的一个是,通过堆分配,您可以最灵活地控制对象的生命周期(从 malloc/callocfree< /代码>);
  • 堆栈空间通常是比堆空间更有限的资源,至少在默认配置中是这样;
  • 分配堆空间失败可以得到妥善处理,而堆栈空间耗尽通常是无法恢复的。

如果没有灵活的对象生存期,二叉树和链表等有用的数据结构实际上是不可能编写的。

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.

温柔少女心 2024-08-14 14:19:12
  1. 您希望分配在函数调用之后继续存在
  2. 您希望节省堆栈空间(通常限制为几 MB)
  3. 您正在使用可重定位内存(Win16、数据库等),或者希望从分配中恢复失败。
  4. 可变长度任何东西。你可以假装绕过这个,但你的代码会非常糟糕。

最重要的是#1。一旦你进入任何类型的并发,或者 IPC#1 就无处不在。如果没有一些堆分配,即使是大多数重要的单线程应用程序也很难设计。这实际上是在 C/C++ 中伪造一种函数式语言。

  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++.

荆棘i 2024-08-14 14:19:12

所以我想制作一个字符串。我可以将其放在堆上或堆栈上。让我们尝试一下:

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

对于堆栈:

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

现在我将这两个字符串放在各自的位置。后来,我想让它们更长:

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

对于堆栈:

// umm... What?

这只是一个好处,其他人提到了其他好处,但这是一个相当不错的好处。有了堆,我们至少可以尝试让我们分配的空间更大。有了堆栈,我们就只能坚持现有的东西了。如果我们想要增长空间,我们必须预先声明这一切,我们都知道看到这一点有多糟糕:

char username[MAX_BUF_SIZE];

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];
划一舟意中人 2024-08-14 14:19:12

使用堆的最明显的理由是当您调用函数并需要返回未知长度的内容时。有时,调用者可能会将内存块和大小传递给函数,但在其他时候,这是不切实际的,特别是如果返回的内容很复杂(例如,指针飞来飞去的不同对象的集合等)。

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.).

黒涩兲箜 2024-08-14 14:19:12

在很多情况下,尺寸限制是一个巨大的破坏因素。堆栈通常以低兆字节甚至千字节为单位(即堆栈上的所有内容),而所有现代 PC 都允许使用几 GB 的堆。因此,如果您要使用大量数据,则绝对需要堆。

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.

甜中书 2024-08-14 14:19:12

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.

在风中等你 2024-08-14 14:19:12

除了手动控制对象的生命周期(您提到的)之外,使用堆的其他原因还包括:

  • 对对象大小的运行时控制(在程序执行期间,初始大小和“后来”的大小)。

例如,您可以分配一个特定大小的数组,该大小仅在运行时才知道。

随着 C99 中 VLA(可变长度数组)的引入,可以在不使用堆的情况下分配固定运行时大小的数组(这基本上是“alloca”功能的语言级实现)。然而,在其他情况下,即使在 C99 中,您仍然需要堆。

  • 运行时控制对象总数。

例如,当您构建二叉树结构时,您无法提前在堆栈上有意义地分配树的节点。您必须使用堆“按需”分配它们。

  • 低级技术考虑,如有限的堆栈空间(其他人已经提到过)。

当您需要一个大的 I/O 缓冲区时,即使是很短的时间(在单个函数内),从堆中请求它比声明一个大的自动数组更有意义。

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.

合约呢 2024-08-14 14:19:12

堆栈变量(通常称为“自动变量”)最适合用于您希望始终相同且始终较小的事物。

int x;
char foo[32];

都是堆栈分配,这些也在编译时固定。

堆分配的最佳原因是您无法始终知道需要多少空间。您通常只有在程序运行后才知道这一点。您可能知道限制,但只想使用所需的确切空间量。

如果您必须读取一个从 1k 到 50mb 的文件,您不会这样做:-

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

会尝试在堆栈上分配 50mb,这通常会失败,因为堆栈通常限制为 256k。

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.

做个少女永远怀春 2024-08-14 14:19:12

如果您使用整个内存段,堆栈和堆共享相同的“开放”内存空间,并且最终必须到达它们相遇的点。保持它们每个人使用的空间之间的平衡将在以后分配和取消分配内存时摊销成本较小的渐近值。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文