C中是否有自动和动态内存分配的经验规则?[暂停]

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (59)

我目前正在学习C,并且经常不确定如何最好地分配我的内存。我知道我们可以这样做自动或动态内存分配:

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中选择自动或动态内存分配时,两者的重要优缺点是什么?

提问于
用户回答回答于

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

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

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

用户回答回答于

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

过多地更改堆栈指针会降低缓存性能,而缓存是最重要的。

而且,可能会溢出堆栈,并且保护页面,虽然这主要是一个线程的问题,这些线程必须有限大小的堆栈,或者在其他受限的系统上,这些系统无法自动实现主线程堆栈的增长。

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

需要打电话free不应该有任何的担心,有所有的分类的函数(这是C+试图解决的主要问题,也是GNU的__attribute__((cleanup))(扩展)你应该发展出一门始终知道如何去做的学科。

值得注意的是,每个函数取走指针应该有一个“谁负责这个所有权”的概念?常见的所有权模式包括:借用(由较高的堆栈框架拥有)、唯一拥有和共享(通常是重新计算的)所有权,尽管可能有几十个微妙的变体(虽然不是所有的都在同一个程序中)。

所属标签

可能回答问题的人

  • 人生的旅途

    10 粉丝484 提问6 回答
  • 不吃貓的鱼oo

    5 粉丝466 提问6 回答
  • 富有想象力的人

    4 粉丝0 提问5 回答
  • Richel

    8 粉丝0 提问5 回答

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励