简体   繁体   English

使用 [] 运算符而不是使用 malloc 动态分配数组?

[英]Dynamically allocating array with the [] operator instead of using malloc?

I am sure this has been asked a million times but I couldn't find an answer that explained it.我确信这已经被问了一百万次,但我找不到解释它的答案。 I have been told to never do this but I haven't really understood why.有人告诉我永远不要这样做,但我真的不明白为什么。 Why doesn't something like this count as dynamically allocating memory and why is it that bad?为什么这样的事情不能算作动态分配 memory ,为什么那么糟糕?

int a;
scanf("%d",&a);
int arr[a];

This is not dynamic allocation but a variable length array .这不是动态分配,而是可变长度数组

The lifetime of such an array is its enclosing scope, just like an array with a fixed size, so you don't need to worry about deallocation.这种数组的生命周期是它封闭的 scope,就像一个固定大小的数组,所以你不需要担心释放。 These arrays typically reside on the stack, so the size of the stack does put limitations on how big a VLA (or any array) can be.这些 arrays 通常驻留在堆栈中,因此堆栈的大小确实限制了 VLA(或任何阵列)的大小。

If you find that a VLA is too big for the stack, you can always fall back to using malloc .如果您发现 VLA 对于堆栈来说太大,您可以随时退回到使用malloc

Dynamically allocating array with the [] operator instead of using malloc?使用 [] 运算符而不是使用 malloc 动态分配数组?

The [] here is used to define an array .这里的[]用于定义一个数组 [] here, is not an operator. []这里,不是运算符。

int arr[a];

I have been told to never do this but i havent really understood why.有人告诉我永远不要这样做,但我真的不明白为什么。

This mantra applies to many things in C (and life), do not use until you understand how to use it.这个咒语适用于C(和生活)中的许多东西,在您了解如何使用之前不要使用它。

Why doesnt something like this count as dynamically allocating memory为什么这样的事情不能算作动态分配 memory

It is dynamically allocating memory allocation, but usually uses a different memory pool and has a different lifetime than via malloc() .它动态分配 memory 分配,但通常使用不同的 memory 池并且具有与通过malloc()不同的生命周期。

... and why is it that bad? ......为什么它那么糟糕?

int arr[a]; is a variable length array (VLA) and has the following issues:是一个可变长度数组(VLA),存在以下问题:

  • Not always available.并非总是可用。 VLAs supported in C99 and often, but not always, in later versions. VLA 在 C99 中支持,并且在以后的版本中经常(但并非总是)支持。 Research __STDC_NO_VLA__ .研究__STDC_NO_VLA__

  • With int a , code is undefined behavior (UB) when a <= 0 .使用int a ,当a <= 0时,代码是未定义的行为 (UB)。

  • When a is too large, there is no standard mechanism to detect insufficient memory.a太大时,没有标准机制来检测 memory 不足。

VLA better used in controlled smaller size cases. VLA 更好地用于受控的较小尺寸的情况。

First of all, let me tell you that this is called variable length array, and it's an optional feature.首先,让我告诉您,这称为变长数组,它是一个可选功能。 Better not to rely on this feature (or compiler support).最好不要依赖此功能(或编译器支持)。

On the other hand, allocator functions ( malloc() , free() and family) are standard compliant and any conforming compiler / library will support these functions.另一方面,分配器函数( malloc()free()和 family)符合标准,任何符合标准的编译器/库都将支持这些函数。

That said, the differences are mentioned in other answers , primary differences are with scope and portability.也就是说,其他答案中提到了差异,主要差异在于 scope 和便携性。

Why doesnt something like this count as dynamically allocating memory为什么这样的事情不能算作动态分配 memory

That the size of the object is determined at runtime is not sufficient for dynamic allocation.在运行时确定 object 的大小不足以进行动态分配。 Dynamic allocation requires direct or indirect use of one of the functions that specifically performs dynamic memory allocation, with malloc , calloc , and realloc being the main examples.动态分配需要直接或间接使用专门执行动态 memory 分配的函数之一,其中malloccallocrealloc是主要示例。 Your example...你的例子...

 int arr[a];

... does not do this, so the object is not dynamically allocated. ...不这样做,所以 object 不是动态分配的。 You arr is a more-or-less ordinary local variable with variable-length array type.arr是一个或多或少的普通局部变量,具有可变长度数组类型。

Semantically, dynamically allocated objects have "allocated" storage duration, which means that they exist and retain their last-stored value until explicitly deallocated.从语义上讲,动态分配的对象具有“已分配”的存储持续时间,这意味着它们存在并保留其最后存储的值,直到显式释放。 Your arr instead has "automatic" storage duration, which means that it ceases to exist when execution of its innermost containing block terminates.相反,您的arr具有“自动”存储持续时间,这意味着当其最内层包含块的执行终止时它不再存在。

and why is it that bad?为什么那么糟糕?

Opinions vary.意见不一。 VLAs were a required feature in C99, but support was made optional in C11. VLA 在 C99 中是必需的功能,但在 C11 中支持是可选的。 If you use VLAs in your code, then, you limit its portability.如果您在代码中使用 VLA,那么您会限制其可移植性。 C++ does not support them (or at least did not -- I understand that they are now coming to C++, too, and maybe they have already arrived), which may be an issue for some. C++ 不支持它们(或者至少不支持——我知道它们现在也将使用 C++,也许它们已经到了),这对某些人来说可能是个问题。

However, the main risk cited is that the usual and natural implementation of VLAs is to allocate them on the stack, and stack size is typically a lot more limited than heap space.但是,引用的主要风险是 VLA 的通常和自然实现是在堆栈上分配它们,并且堆栈大小通常比堆空间更有限。 In a naive example such as yours, it is easy to create a stack overflow, and this may depend on user input, thus making it both difficult to test and a potential security risk.在像您这样的幼稚示例中,很容易创建堆栈溢出,这可能取决于用户输入,因此既难以测试又存在潜在的安全风险。

I do use VLAs in my code from time to time, but usually in ways that are not subject to the stack-busting risk described above.确实不时在我的代码中使用 VLA,但通常以不受上述堆栈破坏风险影响的方式使用。 I generally look skeptically on admonitions to "never do that", but indeed I would never write the exact code you present for a production application.我通常对“永远不要那样做”的告诫持怀疑态度,但实际上我永远不会编写您为生产应用程序提供的确切代码。

This is an example of a variable length array .这是一个可变长度数组的例子。 Its lifetime is the same as any other auto variable (including fixed-length arrays), so memory for it will be released once you exit its enclosing scope.它的生命周期与任何其他auto变量(包括固定长度数组)相同,因此一旦退出其封闭的 scope,它的 memory 将被释放。

Unlike fixed-length arrays, VLAs cannot be declared at file scope (outside of any function) or with the static keyword, nor can they be declared with an initializer.与固定长度的 arrays 不同,VLA 不能在文件 scope(在任何函数之外)或使用static关键字声明,也不能使用初始化程序声明。 Because of how they are typically managed, they cannot be arbitrarily large.由于它们通常是如何管理的,它们不能任意大。 Despite the name, they cannot be resized once they are defined - the "variable" in variable length only means that their size can be different each time they are defined.尽管有名称,但一旦定义它们就无法调整大小 - 可变长度的“变量”仅意味着它们的大小在每次定义时都可以不同。

VLAs are useful but limited. VLA 有用但有限。 They're great when you need some temporary working storage that's local to a function and doesn't need to be too big (not much bigger than a megabyte or so).当您需要一些 function 本地的临时工作存储并且不需要太大(不超过 1 兆字节左右)时,它们非常有用。

They were only introduced in C99 and made optional in C11, so support for them may be a little spotty.它们仅在 C99 中引入,在 C11 中成为可选,因此对它们的支持可能有点参差不齐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM