我在C语言中是否过度使用了malloc函数?

4

我正在学习C语言。我知道malloc()函数分配的字节块在用户请求之外不能被更改或破坏,但我发现自己经常使用它。确切地说,每当我想创建一个结构体或其任何内容以便将来引用时,我都会使用malloc。我也知道在使用完毕后需要free()已分配的内存。

我的malloc使用是否正确?


9
如果你只需要一个具有自动存储期和块作用域的本地对象(即一个局部对象),那么这是正确但过于热心的。一般来说:如果你在同一个函数中调用malloc()free(),那么你应该考虑摆脱它们并静态分配结构体/数组/其他内容。 - user529758
2
你没有展示任何代码,所以你的问题在这里不适合讨论。请阅读关于内存损坏内存泄漏和使用valgrind的相关内容。 - Basile Starynkevitch
8
仅仅因为一个问题没有代码并不意味着它是离题的。 - icktoofay
@icktoofay并非总是如此,但在99.5%的情况下是这样的。我认为OP的问题不是典型的“高于平均水平”的例外情况。 - user529758
作为专业 C 语言编程指南之一,避免使用动态内存就像避开瘟疫一样,即使必须使用动态内存,也应该尽可能地使用静态分配的内存。因为在你的代码中增加复杂性和时间(更多的功能、线程等)只会导致出错的可能性增加(双重释放、悬空指针、未释放但未访问的内存),这是不可避免的。 - fkl
虽然我们在提供其他选项,但alloca.h可能仍然是一个不错的选择。它可以在运行时在堆栈上获取内存,并且仍然不需要手动释放它。https://dev59.com/0GUo5IYBdhLWcg3w9jR4 - fkl
3个回答

2
动态内存分配(malloc及其相关函数)有两个原因:
  • 您的数据需要在分配它的范围之外持久存在(例如多线程)
  • 您要分配的内容对于您的堆栈而言太大了
您应该真正避免为任何其他原因分配动态内存。自动(堆栈)变量更不容易出错,并且在范围结束时会自动释放。
像您所说的“损坏的内存”只能真正由于糟糕的编程而产生,可能会在堆栈和堆上发生,您不应该依赖动态内存来提供缓冲区溢出或其他导致内存损坏的错误的安全性。
C标准库中的许多函数之所以将指向缓冲区的指针作为参数传递以放置结果,是因为它允许您在堆栈上分配这些缓冲区。例如:
 ssize_t read(int fd, void *buf, size_t count);

另外,正如另一篇答案所提到的:您的堆栈内存已经在CPU缓存中,因此可以更快地访问。

1
请同时考虑其他类型的分配:
int foo;

在代码块之外分配的变量是全局变量,在整个进程的生命周期内都是有效的,并且对程序的其他模块可见。
static int foo;

块之外的内容相同,但仅在实际模块中可见。

int foo;

在一个代码块中的内容只有在代码块运行时才存在,然后就被销毁了。
static int foo;

块内的内容只在该块中可见,但它会保留其值直到整个进程结束。

我正在进行大量的嵌入式C编码,并且绝对禁止使用malloc()。但这是完全可能的。通常情况下,如果您在编译时不知道问题的大小,则需要malloc()。但即使在某些情况下,您也可以使用其他技术(如递归,基于行的处理等)替换动态内存分配。


请注意,使用“静态”数据通常与多线程不兼容。因此,这可能不是一个普遍的建议。 - Basile Starynkevitch
虽然我们建议其他选项,但alloca.h仍然是一个不错的选择。在运行时在堆栈上获取内存,而且仍然不需要手动释放它。https://dev59.com/0GUo5IYBdhLWcg3w9jR4 - fkl

0

这取决于您所说的是什么

不能在没有用户请求的情况下更改或损坏

如果您指的是代码-通常称为客户端,而不是用户。但仍然不清楚您的意思。但这不是重点。

重点是malloc()是用于动态内存分配的函数之一。这意味着您可以将此函数返回的地址传递到其他地方,并且存储在那里的数据将一直存在,直到手动释放为止。与静态内存分配不同,后者在超出范围时会自动释放。

因此,如果由malloc()分配的内存在同一范围内被释放,您可能不应该使用它,因为这是无意义的,并且静态分配速度更快,因为CPU更容易缓存并且在程序启动时初始化,而不是在运行时像堆分配的内存。


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