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

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

你能举个例子解释一下吗?

321971 次浏览

静态分配:

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

动态内存分配:

  • 如果程序单元处于活动状态,变量将被分配 只有
  • 分配完成 期间程序的执行
  • 它使用称为 一大堆的数据结构来实现动态分配
  • 更有效率
  • 内存可重用性内存可重用性。内存可以释放时,不需要

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

int a[10];

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

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

而后者应该是 自由d,因为 C 语言中没有垃圾收集器(GC)。

free(a);

分配有三种类型: 静态分配、自动分配和动态分配。

静态分配 意味着在程序启动时为变量分配内存。在创建程序时,大小是固定的。它适用于全局变量、文件范围变量和函数内定义的 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);

静态分配: 编译器为声明的变量分配所需的内存空间。通过使用操作符的地址,可以获得保留的地址,这个地址可以分配给一个指针变量。由于大多数声明的变量都有静态内存,这种将指针值赋给指针变量的方法称为静态分配。在编译时分配内存。

动态内存分配: 它使用 malloc ()或 calloc ()等函数动态地获取内存。如果这些函数用于动态地获取内存,并且这些函数返回的值被分配给指针变量,那么这种分配就称为动态内存分配。内存在运行时被分配。

静态分配动态内存分配的区别

内存是在程序执行开始之前分配的 (During Compilation).
内存是在程序执行期间分配的。

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

Variables remain permanently allocated.
只有当程序单元处于活动状态时才分配。

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

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

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

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

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

动态内存分配

Is memory allocated at runtime using calloc(), malloc() and friends. It is sometimes also referred to as 'heap' memory, although it has nothing to do with the heap data-structure < sup > ref .

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

堆内存是持久的,直到调用 free()。换句话说,您控制变量的生命周期。

自动内存分配

这就是通常所说的“堆栈”内存,当您进入一个新的作用域时(通常是在调用堆栈上推送一个新函数时)就会分配这个内存。一旦您移出作用域,自动内存地址的值就是未定义的,它是一个 error to access them

int a = 43;

Note that scope does not necessarily mean function. Scopes can nest within a function, and the variable will be in-scope only within the block in which it was declared. Note also that where this memory is allocated is not specified. (On a 理智 system it will be on the stack, or registers for optimisation)

静态分配

在编译时 *分配,静态内存中变量的生存期是 程序的生命周期

在 C 语言中,可以使用 static关键字来分配静态内存。

事情变得越来越有趣。当 extern变量为 defined时,编译器为其分配内存。当 extern变量为 声明时,编译器要求该变量在其他地方为 defined。未能声明/定义 extern变量将导致链接问题,而未能声明/定义 static变量将导致编译问题。

在 file 作用域中,static 关键字是可选的(在函数之外) :

int a = 32;

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

static int a = 32;

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

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

* 静态分配须知

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

考虑 静态内存的分配由编译器处理。可能比考虑 在编译时分配更好。

例如,编译器可以在已编译的二进制文件中创建一个大的 data段,当程序装入内存时,程序的 data段中的地址将被用作分配内存的位置。如果使用大量的静态内存,这样做的明显缺点是使编译后的二进制文件变得非常大。用不到半打代码行就可以写出几千兆字节的二进制文件。另一个选择是编译器注入初始化代码,在程序执行之前以其他方式分配内存。此代码将根据目标平台和操作系统的不同而有所不同。在实践中,现代编译器使用启发式来决定使用这些选项中的哪一个。您可以自己编写一个小的 C 程序来尝试这种方法,该程序可以分配10k、1m、10m、100m、1G 或10G 项目的大型静态数组。对于许多编译器来说,二进制大小将随着数组的大小线性增长,过了某个特定点后,编译器将使用另一种分配策略,二进制大小将再次收缩。

寄存器内存

最后一个内存类是“ register”变量。正如预期的那样,寄存器变量应该在 CPU 的寄存器上分配,但是决策实际上留给了编译器。不能使用 address-of 将寄存器变量转换为引用。

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

大多数现代编译器在选择哪些变量应该放入寄存器方面都比您聪明:)

参考文献:

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