什么时候必须使用malloc来分配内存?

时间:2010-07-04 19:10:29

标签: c memory-management malloc

1)
对于哪些数据类型,我必须使用malloc分配内存?

  • 对于类似结构,指针的类型,基本数据类型除外,如int
  • 适用于所有类型?

2)
为什么我可以运行此代码?为什么不崩溃?我假设我需要先为结构分配内存。

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;
 foo2.b = (uint32*)malloc(sizeof(uint32));
 *foo2.b = 123;
}

使用

不是更好
foo* foo2 = malloc(sizeof(foo));

第3) foo.b如何设置?是引用随机内存还是NULL?

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;

}

7 个答案:

答案 0 :(得分:18)

C中的所有类型都可以动态,自动(在堆栈上)或静态分配。问题不是类型,而是你想要的生命周期 - 当你希望一个对象存在于创建它的函数范围之外时,或者你事先不知道你需要多大的东西时,你可以使用malloc。

答案 1 :(得分:9)

编辑以解决您编号的问题。

  1. 您必须使用malloc分配数据类型。只有当您希望指针类型指向有效内存时,才能使用一元&(地址)运算符或malloc()或某些相关函数。

  2. 您的代码没有任何问题 - 行:

    foo foo2;
    

    在堆栈上分配一个结构 - 然后一切正常。在这个意义上,结构与任何其他变量没有区别。使用自动变量(堆栈分配)或全局变量或malloc()并不是更好或更糟,它们都是不同的,具有不同的语义和选择它们的不同理由。

  3. 在#3的示例中,foo2.b的值未定义。在您明确初始化它之前,任何自动变量都有一个未定义和不确定的值。

答案 2 :(得分:3)

您必须使用malloc分配您希望手动管理的任何内存,而不是自动分配。如果存储的是intdoublestruct或其他内容,则无关紧要; malloc就是手动内存管理。

当你创建一个没有malloc的变量时,它存储在堆栈中,当它超出范围时,它的内存会自动回收。当变量不再可访问时,变量超出范围;例如当声明变量的块或函数结束时。

使用malloc分配内存时,它存储在中,malloc返回指向此内存的指针。直到你在其上调用free之后才会回收此内存,无论指针是否仍然可以访问(当没有指针留给堆分配的内存时,这是内存泄漏)。这意味着您可以继续使用在分配的块或函数之后分配的内存,但另一方面,您现在有责任在完成它时手动释放它。

在您的示例中,foo2位于堆栈中,并在main结束时自动取消分配。但是,foo2.b指向的内存将自动解除分配,因为它位于堆上。这在您的示例中不是问题,因为在程序结束时所有内存都返回到操作系统,但如果它位于main以外的函数中,则会导致内存泄漏。

答案 3 :(得分:2)

foo foo2;自动在堆栈上分配结构,当封闭函数(在本例中为main)结束时,它会自动释放。

如果需要在封闭范围结束后保持结构,则只需使用malloc在堆上分配内存。当对象太大而无法放入堆栈时,您可能还需要执行此操作。

答案 4 :(得分:2)

  

2)为什么我可以运行此代码?它为什么不崩溃?

代码从不引用未定义的内存或NULL。为什么会崩溃? (你写的内存泄漏,但可能是因为你只显示部分代码而且在给定的程序中它不是问题。)

您建议的替代代码也可以使用,但默认情况下,从malloc返回的内存也未初始化。 (我曾经使用过一个自定义内存分配器,默认情况下用?个字符填充返回的内存块。规则仍然完全合法。注意calloc返回一个指向零初始化内存的指针;如果{这就是你想要的。)

  

3) foo.b如何设定?是引用随机存储器还是NULL?

随机记忆。堆栈分配的结构不会为您初始化。

答案 5 :(得分:1)

你可以做到,但这还不够。

因为,第二个字段是指针,必须将其设置为有效地址。其中一种方法是分配内存(使用malloc)。

至于你的第一个问题 - 必须手动管理对象的生命周期时使用malloc。

例如,第二个代码可以重写为:

int main(int argc, char* argv[])
{
 foo foo2; uint32 b;
 foo2.a = 3;
 foo2.b = &b;
 *foo2.b = 123;
}

这样更好,因为生命周期是相同的,内存现在处于堆栈状态 - 并且不需要被释放。

答案 6 :(得分:1)

结构实例(“foo2”)的内存将在堆栈上分配 - 不需要为此自己分配内存 - 如果使用malloc进行分配,请务必在以后释放内存。 / p>