静态内存分配和动态内存分配之间的区别

问题描述 投票:69回答:7

我想知道静态内存分配和动态内存分配有什么区别?

你能用任何一个例子解释一下吗?

c memory memory-management dynamic-memory-allocation static-memory-allocation
7个回答
74
投票

分配有三种类型 - 静态,自动和动态。

静态分配意味着在程序启动时分配变量的内存。创建程序时,大小是固定的。它适用于全局变量,文件范围变量以及在函数内定义的static限定的变量。

为函数内部定义的(非静态)变量进行自动内存分配,并且通常存储在堆栈中(尽管C标准并未强制要求使用堆栈)。您不必使用它们来保留额外的内存,但另一方面,也限制了对此内存的生命周期的控制。例如:函数中的自动变量仅在函数完成之前存在。

void func() {
    int i; /* `i` only exists during `func` */
}

动态内存分配有点不同。您现在可以控制这些内存位置的确切大小和生命周期。如果你没有释放它,你将遇到内存泄漏,这可能会导致应用程序崩溃,因为在某些时候,系统无法分配更多的内存。

int* func() {
    int* mem = malloc(1024);
    return mem;
}

int* mem = func(); /* still accessible */

在上面的示例中,即使函数终止,分配的内存仍然有效且可访问。完成内存后,你必须释放它:

free(mem);

97
投票

这是一个标准的面试问题:

动态内存分配

是使用calloc()malloc()和朋友在运行时分配的内存。它有时也被称为“堆”内存,尽管它与堆数据结构ref无关。

int * a = malloc(sizeof(int));

在调用free()之前,堆内存是持久的。换句话说,您可以控制变量的生命周期。

自动内存分配

这就是通常所说的“堆栈”内存,并在您输入新范围时分配(通常在调用堆栈上推送新函数时)。一旦你离开范围,自动内存地址的值是未定义的,它是一个error to access them

int a = 43;

请注意,范围不一定意味着功能。范围可以嵌套在一个函数中,并且该变量仅在声明它的块内是范围内的。另请注意,未指定分配此内存的位置。 (在一个理智的系统上,它将在堆栈上,或注册优化)

静态内存分配

在编译时分配,静态内存中变量的生命周期是lifetime of the program

在C中,可以使用static关键字分配静态内存。范围仅是编译单元。

事情变得更有趣when the extern keyword is considered。当定义extern变量时,编译器为其分配内存。当声明extern变量时,编译器要求在其他地方定义变量。未能声明/定义extern变量将导致链接问题,而声明/定义static变量失败将导致编译问题。

在文件范围内,static关键字是可选的(在函数之外):

int a = 32;

但不是在函数范围内(函数内部):

static int a = 32;

从技术上讲,externstatic是C中两个独立的变量类。

extern int a; /* Declaration */
int a; /* Definition */

注册记忆

最后一个内存类是'register'变量。正如所料,寄存器变量应该分配在CPU的寄存器中,但实际上决定是由编译器决定的。您不能使用address-of将寄存器变量转换为引用。

register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */

大多数现代编译器都比你选择哪些变量放在寄存器中更聪明:)

参考文献:

有关静态内存分配的说明

说编译时分配静态内存有点令人困惑,特别是如果我们开始考虑编译机器和主机可能不相同或者甚至不在同一架构上。

认为静态内存的分配由编译器处理而不是在编译时分配可能更好。例如,编译器可以在编译的二进制文件中创建大的data部分,并且当程序加载到存储器中时,程序的data段内的地址将用作分配的存储器的位置。如果使用大量静态内存,这具有使编译的二进制文件非常大的明显缺点。可以编写一个从不到六行代码生成的数千兆字节二进制文件。另一种选择是编译器注入初始化代码,该代码将在程序执行之前以其他方式分配内存。此代码将根据目标平台和操作系统而有所不同。实际上,现代编译器使用启发式方法来决定使用哪些选项。您可以通过编写一个分配10k,1m,10m,100m,1G或10G项目的大型静态数组的小型C程序来自行尝试。对于许多编译器,二进制大小将随着数组的大小而线性增长,并且经过某一点,当编译器使用另一个分配策略时,它将再次缩小。


3
投票

静态内存分配:

  • 变量永久分配
  • 分配在程序执行之前完成
  • 它使用称为堆栈的数据结构来实现静态分配
  • 效率较低
  • 没有内存可重用性

动态内存分配:

  • 只有在程序单元激活时才会分配变量
  • 分配在程序执行期间完成
  • 它使用称为heap的数据结构来实现动态分配
  • 更高效
  • 有内存可重用性。不需要时可以释放内存

2
投票

静态内存分配:编译器为声明的变量分配所需的内存空间。通过使用运算符的地址,获取保留的地址,并将此地址分配给指针变量。因为大多数声明的变量都有静态内存,将指针值赋给指针变量的方法称为静态内存分配。在编译期间分配内存。

动态内存分配:它使用诸如malloc()或calloc()之类的函数来动态获取内存。如果这些函数用于动态获取内存并且这些函数返回的值被赋予指针变量,则这种赋值称为动态内存allocation.memory在运行时被绑定。


1
投票

静态记忆分配与动态记忆分配的区别

在程序执行开始之前(编译期间)分配内存。 在程序执行期间分配内存。

执行期间不执行内存分配或释放操作。 内存绑定在执行期间建立并销毁。

变量保持永久分配。 仅在程序单元处于活动状态时分配。

使用堆栈和堆实现。 使用数据段实现。

访问变量需要指针。 不需要动态分配指针。

执行速度比动态更快。 执行速度比静态慢。

需要更多内存空间。 需要更少的内存空间。


0
投票

静态内存分配在编译期间执行pf程序之前分配内存。动态内存分配是在运行时执行程序期间的内存。


-1
投票

静态内存分配。分配的内存将在堆栈中。

int a[10];

动态内存分配。分配的内存将在堆中。

int *a = malloc(sizeof(int) * 10);

应该释放后者,因为C中没有垃圾收集器(GC)。

free(a);
© www.soinside.com 2019 - 2024. All rights reserved.