自动vs动态内存分配:要考虑什么? [关闭]

问题描述 投票:4回答:2

在C中,我们可以分配内存automaticallydynamically

size_t foo = 128;
char str1[64];            // Automatic
char str2[foo]            // Automatic (variable-length, C99)
char *str3 = malloc(64);  // Dynamic
char *str4 = malloc(foo); // Dynamic

使用自动分配,变量的作用域有限,并且通常在堆栈上分配内存,而动态分配使用堆。

让我们坚持使用字符串,说一个函数应该返回它以某种方式创建的字符串。似乎有两种常见的做法,都可以在标准库函数中看到:

  1. 获取缓冲区和大小,然后写入提供的缓冲区
  2. malloc()分配缓冲区并返回指向它的指针

第一个优点是我们不需要记住free()内存。另一方面,我们需要提供两个附加参数,并且需要以某种方式从外部确定缓冲区应具有的大小:

char str1[128];              // Let's hope this is large enough!
fill_my_buffer(str1, 128);   // Might need more than 128, who knows

char *str2 = return_a_ptr(); // Just give me a pointer
size_t len = strlen(str2);   // Ah, so that's what we got!

在C中自动或动态内存分配之间进行选择时应考虑哪些(其他)注意事项?


该问题基于观点而关闭,但我坚信对于这两种方法,都应该可以编制一份全面的目标利弊清单。

c memory-management allocation
2个回答
4
投票

经验法则是,应避免在堆栈上分配“大”笔款项。一个页面(4096个字节)或两个页面是可以的,但是任何较大的页面都应该堆分配。

过多更改堆栈指针将破坏您的缓存性能,而缓存为王。

此外,您可能会溢出堆栈和保护页面miss,尽管这仅主要是线程的问题,这些线程必须具有有限的堆栈大小,或者在其他无法自动维护主线程的受限系统上线程堆栈增长。


除此之外,主要问题是语义:这个(小的)对象是否“属于”该堆栈框架,或者它需要生存不同的时间段(更长或更短)。

根本不需要担心需要调用free,所有sorts函数都必须成对调用(这是C ++试图解决的主要问题,也是GNU的[ C0]扩展名),您应该养成始终知道这样做的纪律。

值得注意的是,takes指针的每个函数都应具有“谁负责此所有权”的概念?常见的所有权模型包括:借用的(由更高的堆栈框架拥有),唯一拥有的和共享的(通常是重新引用的)所有权,尽管可以存在许多微妙的变体(尽管并非同一程序中的所有变体)。


2
投票

基本上是一个判断调用,调用代码可以知道缓冲区可能有多大吗?

  • 如果是这样,最好提供缓冲区,并且被调用的代码必须确保它不会溢出(这反过来意味着接口必须指定所提供缓冲区的大小)。
  • 如果没有,那么被调用的代码应该分配并返回内存。

调用者提供的缓冲区的复杂性是“当提供的空间不够大时该怎么办”。调用方提供的缓冲区的复杂性在于确保适当释放它,并确定如果内存分配失败该怎么办。

© www.soinside.com 2019 - 2024. All rights reserved.