C

时间:2017-01-02 07:52:42

标签: c dynamic-memory-allocation static-memory-allocation

考虑以下C代码:

#include <stdio.h>
#include<stdlib.h>

int main() {

    int arrSize;

    scanf("%d", &arrSize);

    printf("%d\n",arrSize);

    int *dynArr = (int *)malloc(sizeof(int)*arrSize);

    int arr1[arrSize];

    return 0;
}

在上面的代码中,arrSize是作为用户输入的数组的大小。 以下观察结果是否正确:

i) dynArr 是一个动态数组,在运行时从堆部分分配内存。可以使用 realloc 函数修改dynArr的大小。

ⅱ)。 arr1 也在运行时分配内存,但不是动态的,即它们的大小无法修改。内存是从堆栈或数据部分分配的。 (不确定分配内存的堆或堆栈/数据部分以及原因)。

4 个答案:

答案 0 :(得分:5)

  

i)dynArr是一个动态数组,在运行时分配内存   从堆部分。可以使用realloc修改dynArr的大小   功能

是的,如果main可以找到足够大的块。虽然从技术上讲,指针不是数组。它指向到数组的第一个元素

  

ⅱ)。 arr1在运行时也分配了内存,但不是动态的   即它们的大小不能修改。内存从堆栈中分配   或数据部分。 (不确定从哪个部分堆或堆栈/数据   内存已分配,为什么)。

数组的大小是动态的,它的生命周期不是。它会在malloc返回的那一刻自动回收。可变长度数组通常在调用堆栈上分配。是的,一旦你宣布它就不能改变它的大小。

如果您现在想知道何时使用一个而不是另一个,则需要考虑以下几点:

  1. 为调用堆栈保留的内存是有限的(远远超过堆)。如果你宣布一个巨大的VLA,很容易溢出。

  2. malloc返回的内存及其亲属可以比分配它的堆栈帧更长。

  3. 通常,分配VLA比使用{{1}}分配内存要快。一个是堆栈帧指针的简单进展,而另一个是堆的内存分配器及其逻辑。

答案 1 :(得分:3)

  

dynArr是一个动态数组,在运行时从堆部分分配内存。可以使用dynArr函数修改realloc的大小。

  • dynArr指针,使用malloc()返回的指针进行初始化。记得,arrays are not pointers and vice-versa。在某些情况中,数组名称衰减为指向数组第一个元素的指针,但这并不能使两者相同。

  • dynArr的大小是指针的大小,不是它指向的内存位置的大小。使用正确的单词,in可以表示为,指向的内存大小可以使用realloc()进行更改。

  

arr1在运行时也会分配内存,但不是动态的,即它们的大小无法修改。内存是从堆栈或数据部分分配的。 (不确定分配内存的堆或堆栈/数据部分以及原因)。

这称为variable length array。其他观点是正确的。

引用C11,章节§6.7.6.2

  

如果size是一个不是整数常量表达式的表达式:如果它出现在a中   在函数原型范围内声明,它被视为被*替换;除此以外,   每次评估时,它的值应大于零。每个实例的大小   可变长度数组类型在其生命周期内不会改变。

答案 2 :(得分:1)

它从可用内存存储分配内存。现在,在C ...的情况下,内存中没有任何内容称为堆和堆栈。在C的情况下,我们在逻辑上考虑这一点。(在C的实现中)]

我们唯一担心的是,即使声明的范围是否结束,我们是否需要您想要活着的东西。

对于堆来说就是这种情况..对于堆栈它不是。

在您的情况下

int arr1[arrSize];分配在存储此主函数局部变量的同一帧上。

动态分配

  

您可以控制这些内存的确切大小和生命周期   位置。如果你没有释放它,你就会遇到内存泄漏问题   可能会导致您的应用程序崩溃,因为它在某些时候不能   分配更多的内存。 (dynArr

实际上...

  

堆是计算机内存中未管理的区域   自动为您服务,不受CPU的严密管理。它是   一个更自由浮动的内存区域(并且更大)。分配   堆上的内存,必须使用malloc()或calloc()   内置C函数。

     

一旦你在堆上分配了内存,你就可以了   一旦你负责使用free()来释放那个记忆   不再需要了。如果你没有这样做,你的程序就会有   所谓的内存泄漏。也就是说,堆上的内存仍然存在   被搁置(并且不会被其他进程使用)。

堆栈

  

它是计算机内存的一个特殊区域,可以临时存储   每个函数创建的变量(包括main()函数)。   堆栈是&#34; LIFO&#34; (后进先出)数据结构,即   由CPU密切管理和优化。每次都有功能   声明一个新的变量,它是&#34;推的&#34;到堆栈上。 然后每一个   函数退出的时间,所有变量都被压入堆栈   该功能被释放(也就是说,它们被删除)。一旦   释放堆栈变量,该内存区域变为可用   其他堆栈变量。

资源

答案 3 :(得分:0)

实际上,Google C ++样式指南中不允许使用可变长度数组。它具有自然的语法并且效率很高,但是,因为它们分配了数据依赖的堆栈空间量,它可以触发严重且神秘的内存覆盖错误:

有时“它在我的机器上运行良好,但在生产中神秘地死了”。