【问题标题】:What's the difference between a VLA and dynamic memory allocation via malloc?VLA 和通过 malloc 进行动态内存分配有什么区别?
【发布时间】:2022-01-07 08:38:03
【问题描述】:

我很好奇:

两者有什么区别:

const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

和:

char Buffer[MAX_BUF];

【问题讨论】:

  • 鉴于MAX_BUFconst,第二个示例真的是VLA 吗?
  • @juanchopanza 先生,如果我没记错的话,在C++ 中,const 变量是一个常量,但在C 中,const 变量实际上是const-qualified ,而不是实际常数。所以,第二个是VLA,如果我错了,请纠正我。
  • @SouravGhosh 好的,谢谢。这是一个真正的问题。我不太了解C。
  • @juanchopanza 我的C++ 技能太糟糕了,在那种情况下我几乎是隐形的。只是“碰巧”知道一些案例,比如这个。 :-)
  • 哪些代码需要更少的执行时间?

标签: c pointers initialization malloc variable-length-array


【解决方案1】:
  • 案例 1:在

     char Buffer[MAX_BUF];
    

    Buffer 是一个大小为MAX_BUF数组。分配技术称为VLA

  • 案例 2:在

    const int MAX_BUF = 1000;
    char* Buffer = malloc(MAX_BUF);
    

    Buffer 是一个指针,它分配了一个大小为MAX_BUF 的内存,即1000

而且,数组与指针相同,而C-FAQ has a Very Good collection detailing the reasons

在可用性和行为方面的主要区别是:

  1. (1) 在堆栈上,通常注意,而 (2) 在堆上,总是。
  2. (1) 分配后大小固定,(2) 可以调整大小。
  3. (1) 在调用封闭函数时分配,并且具有块作用域 OTOH,(2) 在运行时动态分配内存,返回的内存具有从分配到释放的生命周期。
  4. (1)分配的内存不需要由程序员管理,而在(2)所有malloc()d内存应该是free()d。 [礼貌:Giorgi]

注意:Wiki

例如,GNU C 编译器为堆栈上的 VLA 分配内存。

【讨论】:

  • 旁白:“当 (2) 始终在堆上时。” --> 并非总是如此。堆、栈和分配细节的概念是实现定义的。剩下的3分不错。
【解决方案2】:

除了其他人所说的之外,我将在内存管理方面添加一些信息。

1) 主要区别在这里:

const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

您需要手动管理分配的内存,例如,使用完后释放Buffer。忘记free它(或释放它两次)可能会导致麻烦。

2) 第二种情况:

char Buffer[MAX_BUF];

你不需要释放任何东西。它会自动销毁。因此,您避免了处理内存的任务——这很好。 您应该尝试始终评估您需要哪种方法。

一些要点。

  • 由于第二个是在堆栈上分配的,因此在需要创建大型数组时也采用第一种方法 - 因为堆上通常有更多可用内存。
  • 此外,如果您在方法中使用第二种方法创建数组,则对象的生命周期将是该方法 - 您将无法在该方法之外使用该数组。而动态分配则并非如此。

【讨论】:

  • 不错。我和@coolguy 都错过了free()-ing 角度。 :-)
  • 我添加了这个,带有属性。 :-)
  • @SouravGhosh:我明白了,很好。
【解决方案3】:
char* Buffer = malloc(MAX_BUF);

创建一个char指针Buffer,通过malloc动态分配MAX_BUF字节的内存并使Buffer指向分配空间的开始。此内存在堆上分配。

char Buffer[MAX_BUF];

创建一个大小为MAX_BUF 的数组Buffer,最多可容纳MAX_BUF 个字符。请注意,您正在创建 Variable Length ArrayC99 中引入的功能),因为 MAX_BUF 是一个变量。这个数组可以在栈上创建。

【讨论】:

  • 请注意,从技术上讲,该数组是 VLA(可变长度数组),因为 MAX_BUF 不是编译时常量。
  • 谢谢。我错过了。
【解决方案4】:

最显着的区别是范围。 VLA 数组仅在声明它的范围内有效,而动态数组在程序中的任何地方都可用,直到您调用 free()

在实践中,VLA 可能比动态内存更快,以防编译器为 VLA 使用堆栈分配。然而,C 标准并未指定分配 VLA 的位置。

(编译器理论上可以在堆上分配一个 VLA,但是编译器也将负责清理。我认为不存在任何这样的解决方案。我使用的每个编译器总是在堆栈。)

这意味着 VLA 不适合保存大量数据:您将面临堆栈溢出的风险。但是,当您使用动态内存时,这不是问题。

VLA 不具有与动态数组相同的可移植性,因为非常旧的编译器不支持 VLA。理论上,新的 C11 编译器也不必支持 VLA,尽管在这一点上,我知道没有编译器愚蠢到放弃这种支持。


比较/总结:

  • 当本地数据量较小时应使用 VLA,因为它们具有快速的分配时间和自动清理功能。
  • 数据量大时应使用动态数组,防止堆栈溢出。
  • 当数据需要在函数执行后持续存在并且在程序的其他地方可用时,应使用动态数组。
  • 当您有特殊和/或不合理的可移植性要求时,应使用动态数组。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 2023-03-07
  • 2011-03-16
  • 2020-11-12
相关资源
最近更新 更多