我想了解静态内存分配和动态内存分配之间的区别是什么?
您能用示例来解释一下吗?
我想了解静态内存分配和动态内存分配之间的区别是什么?
您能用示例来解释一下吗?
这是一个标准的面试问题:
calloc()
,malloc()
等函数可以在运行时分配内存。有时候也称为“堆”内存,尽管它与堆数据结构无关。参考
int * a = malloc(sizeof(int));
堆内存在调用free()
之前会一直存在。换句话说,你控制变量的生命周期。
这通常被称为“栈”内存,在进入新作用域时分配(通常是将一个新函数推入调用堆栈中)。一旦离开该作用域,自动内存地址的值就未定义了,访问它们是一个错误。
int a = 43;
请注意,"scope"不一定指函数。作用域可以嵌套在函数内部,变量仅在声明它的块范围内有效。还要注意,分配此内存的位置未指定(在正常的系统上,它将位于堆栈或寄存器中以进行优化)。
在编译时分配,静态内存中变量的生命周期是程序的生命周期。
在 C 中,使用 static
关键字可以分配静态内存。其作用域仅限于编译单元。
当考虑 extern
关键字时,事情变得更有趣。定义一个 extern
变量时,编译器会为其分配存储空间。当声明一个 extern
变量时,编译器需要在其他地方定义该变量。未声明/定义extern
变量将导致链接问题,而未声明/定义static
变量将导致编译问题。
在文件范围内,static
关键字是可选的(函数外部):
int a = 32;
但是不适用于函数范围(在函数内部):
static int a = 32;
从技术上讲,extern
和 static
是 C 中两个不同类别的变量。
extern int a; /* Declaration */
int a; /* Definition */
说静态内存是在编译时分配有点令人困惑,尤其是当我们考虑到编译机器和主机可能不相同,甚至不在同一架构上时。
更好的方式是认为静态内存的分配由编译器处理,而不是在编译时分配。
例如,编译器可能会在编译后的二进制文件中创建一个大的 data
段,在程序加载到内存中时,程序的 data
段中的地址将被用作所分配内存的位置。这种方法的明显缺点是,如果使用了大量的静态内存,编译后的二进制文件会非常大。实际上可以通过不到半打代码生成几个GB的二进制文件。另一种选项是让编译器注入初始化代码,在程序执行之前以某种其他方式分配内存。该代码将根据目标平台和操作系统而异。实际上,现代编译器使用启发式算法来决定使用这些选项中的哪一个。您可以通过编写一个分配10k、1m、10m、100m、1G或10G个静态数组的小C程序来尝试此功能。对于许多编译器,二进制文件的大小将随数组大小线性增长,并且在某个点之后将会再次缩小,因为编译器使用另一种分配策略。
最后一个内存类是“寄存器”变量。正如所料,寄存器变量应该分配在CPU的寄存器中,但实际上决策权留给了编译器。您不能通过使用地址引用来将寄存器变量转换为引用。
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
大多数现代编译器比你更聪明地选择应该放在寄存器中的变量 :)
内存分配有三种类型——静态、自动和动态。
静态分配意味着在程序启动时为您的变量分配内存。程序创建时大小是固定的。它适用于全局变量、文件范围变量以及函数内定义了 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()等函数动态获取内存。如果使用这些函数动态获取内存并将其返回的值分配给指针变量,则此类分配称为动态内存分配。内存在运行时分配。
静态内存分配和动态内存分配的区别
在程序执行之前(编译期间)分配内存。
在程序执行期间分配内存。
执行期间不执行任何内存分配或释放操作。
在执行期间建立和销毁内存绑定。
变量保持永久分配。
仅在程序单元处于活动状态时分配。
使用堆栈和堆实现。
使用数据段实现。
需要指针来访问变量。
不需要动态分配的指针。
比动态执行更快。
比静态执行更慢。
需要更多的内存空间。
需要较少的内存空间。
静态内存分配是在编译时程序执行之前分配内存。 动态内存分配是在运行时程序执行期间分配内存。
静态内存分配。分配的内存将在堆栈中。
int a[10];
动态内存分配。分配的内存将在堆中。
int *a = malloc(sizeof(int) * 10);
而且后者应该免费,因为 C 语言没有垃圾回收器(GC)。
free(a);
int * a = malloc(sizeof(*a));
,以避免重复写a
的类型。如果a
的类型发生变化,这种方式会更加方便。 - Shahbaz