在C语言中什么时候需要使用malloc?

16

我认为所有的malloc(sizeof(structure))都可以用这种方式替换:

char[sizeof(structure)]

那么,什么时候需要使用malloc函数呢?


尽管语法相似,C和C++是非常不同的编程语言。特别是在动态内存方面,两者差异很大。在C++中甚至不应该使用malloc()。由于您的问题没有C++标签,我将从标题中删除"C++"。 - sbi
以上的内存不是从堆栈中占用的吗?如果我们使用 malloc,它将在堆中占用。据我所知,如果要求占用非常大量的内存可能会导致溢出,请评论我是否错误。 - user379888
8个回答

27
  • 当你不知道需要多少个某种对象时(例如链表元素);
  • 当你需要具有仅在运行时已知大小的数据结构(例如基于未知输入的字符串);这在C99中引入了可变长度数组(VLA),但请参见下一点:
  • 当您知道它们的大小(或者可以使用VLAs),但它太大了无法在堆栈上处理(通常最多几MB),并且使这样的事情全局化毫无意义(例如大矢量操作)时;
  • 当您需要拥有对象的生命周期与自动变量不同,自动变量是限制范围的(=>在声明它们的作用域退出执行时被销毁),可以具有不同生命周期的不同对象之间共享(例如必须在不同对象之间共享数据,并在没有人再使用它时删除)。

请注意,完全没有动态内存分配并非不可能(例如整个rockbox项目几乎没有使用它),但有些情况实际上需要通过使用大型静态缓冲区并编写自己的分配器来模拟它。

顺便说一下,在C++中,您永远不会使用malloc()/free(),而是使用运算符newdelete


相关:一个案例,在其中尝试在没有malloc的情况下工作被证明是一件大麻烦。


我为您提供详尽的列表点赞。请注意,该问题没有C++标签,因此我从标题中删除了"C++"。 - sbi
谢谢您。关于C++的事情,我写了那个代码,因为问题中提到了C++,但这并没有改变太多。 - Matteo Italia
据我所知,new 必须为您请求的类型提供正确对齐的内存,因此它应该能够为任何类型分配对齐的内存(如果您需要非对齐的内存,请请求一个 char 数组)。但是,使用 new 分配的内存无法重新分配。 - Matteo Italia
据我所知,避免内存碎片化是分配器的职责之一(因此malloc/任何操作系统函数在内部调用时应该处理它);出于性能原因,在特定情况下可能需要编写自己的分配器(如果您使用特定模式的内存等),但通常情况下malloc就足够了。 - Matteo Italia
总的来说,是的,你是正确的。但对于服务器级应用程序,您需要垃圾收集库或具有紧密内存分配方案。 - yadab
显示剩余6条评论

9
您将使用malloc动态分配内存,原因可能是:
  • 您不知道在编译时需要多少内存,
  • 您希望稍后能够重新分配内存(例如使用realloc),
  • 您希望能够更早地丢弃已分配的内存,而不是等待变量作用域的释放。

我理解您的想法。您可能认为可以始终使用声明性语法来处理这些问题,甚至使用变量来声明内存空间的大小,但这样做会:

  • 非标准化,
  • 使您的控制力降低,
  • 可能会使用更多内存,因为您需要复制而不是重新分配。

您可能会逐渐理解这一点,不必担心。

此外,您应该尝试了解更多关于内存模型的知识。使用动态分配和静态分配时,不使用相同的内存空间。

对于初学者,请访问以下网站获取有关指针的详细信息:


友情建议:我不知道您是在*NIX还是Windows上开发C,但无论如何,如果您使用gcc,我建议在自学时使用以下编译标志:

  -Wall -ansi -pedantic -Wstrict-prototypes

3

我建议您了解动态内存分配。显然您对它并不熟悉。

二者的主要区别在于,使用malloc()分配的内存会一直存在,直到您结束它。而静态内存,例如char buff[10];则只存在于函数作用域中。


如果在函数内定义了 char buff[10],它具有自动存储期而不是静态存储期。 - Van Tr

1

malloc是一种动态内存分配器,它可以帮助您根据需要为变量分配内存,从而减少内存损失。它还受realloc()函数的支持,通过该函数,您可以编辑先前通过malloc()或calloc()定义的所需内存。因此,简而言之,我们可以说malloc()可用于管理内存空间并利用必要的内存而不浪费它。


1
你不应该按照你提出的方式来做。其他人已经告诉过你在堆上分配存储空间和在函数栈上分配的区别。但如果你确实要在栈上进行分配,那么你应该只声明变量:
structure A = { /* initialize correctly */ };

将一个(基本上)未类型化的char数组这样做是没有意义或者没有点的。如果您还需要该兽的地址,那么使用&A获取地址。


0
当您不知道在编译时要分配多少内存时。考虑一个非常简单的程序,您需要在其中将用户输入的数字存储在链表中。在这里,您不知道用户将输入多少个数字。因此,当用户输入一个数字时,您将使用malloc为其创建一个节点,并将其存储在链接列表中。

0

如果你使用char[sizeof(structure)]而不是malloc,那么我认为就不会进行动态内存分配。


-1
除了你的char[]方法无法在运行时调整大小或确定大小外,你的数组可能不适合你要使用它的结构类型。这可能导致未定义的行为

真的吗?我认为,sizeof()返回的不是结构体成员的累加大小,而是它实际占用的大小,否则你将无法执行malloc(sizeof())(从内存对齐的角度来看,这与堆栈上的缓冲区相同。-1)。 - nothrow
@Yossarian:你在考虑成员对齐所引起的填充(padding)问题。我指的是整个struct自身的对齐要求。 - schot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接