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

时间:2011-12-05 12:30:11

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

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

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

7 个答案:

答案 0 :(得分:95)

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

动态内存分配

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

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

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

自动内存分配

这就是通常所说的“堆栈”内存,并在您输入新范围时分配(通常在调用堆栈上推送新函数时)。移出作用域后,自动内存地址的值未定义,为error to access them

int a = 43;

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

静态内存分配

在编译时分配,静态内存中变量的生命周期为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程序来自行尝试。对于许多编译器,二进制大小将随着数组的大小而线性增长,并且超过某一点,当编译器使用另一种分配策略时,它将再次缩小。

答案 1 :(得分:73)

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

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

答案 2 :(得分:3)

静态内存分配:

  • 变量分配永久
  • 分配在 程序执行
  • 之前完成
  • 它使用名为 stack 的数据结构来实现静态分配
  • 效率低下
  • 无内存可重用性

动态内存分配:

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

STATIC MEMORY ALLOCATION & 动态内存分配

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

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

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

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

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

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:-1)

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

int a[10];

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

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

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

free(a);