什么时候应该在C中使用malloc,什么时候不使用?

时间:2009-12-26 16:51:57

标签: c memory memory-management

我理解malloc()是如何工作的。我的问题是,我会看到这样的事情:

#define A_MEGABYTE (1024 * 1024)

char *some_memory;
size_t size_to_allocate = A_MEGABYTE;
some_memory = (char *)malloc(size_to_allocate);
sprintf(some_memory, "Hello World");
printf("%s\n", some_memory);
free(some_memory);

为简洁起见,我省略了错误检查。我的问题是,你不能通过初始化指向内存中某些静态存储的指针来做到这一点吗?也许:

char *some_memory = "Hello World";

你真的需要自己分配内存而不是声明/初始化你需要保留的值?

6 个答案:

答案 0 :(得分:128)

char *some_memory = "Hello World";

正在创建一个指向字符串常量的指针。这意味着字符串“Hello World”将位于内存的只读部分中,您只需指向它。您可以将该字符串用作只读。您无法对其进行更改。例如:

some_memory[0] = 'h';

要求麻烦。

另一方面

some_memory = (char *)malloc(size_to_allocate);

将char数组(变量)和some_memory指向分配的内存。现在这个数组都是读写的。你现在可以这样做:

some_memory[0] = 'h';

并且数组内容更改为“hello World”

答案 1 :(得分:35)

对于这个确切的例子,malloc几乎没用。

需要malloc的主要原因是,您的数据必须具有与代码范围不同的生命周期。您的代码在一个例程中调用malloc,将指针存储在某处,最终在另一个例程中调用free。

第二个原因是C无法知道堆栈上是否有足够的空间用于分配。如果您的代码需要100%健壮,那么使用malloc会更安全,因为您的代码可以知道分配失败并处理它。

答案 2 :(得分:15)

与静态声明(如hello world示例)相比,malloc是一个在运行时分配,重新分配和释放内存的绝佳工具,它们在编译时处理,因此无法更改大小。

因此,当您处理任意大小的数据时,例如读取文件内容或处理套接字并且您不知道要处理的数据的长度时,Malloc总是很有用。

当然,在你给出的一个简单的例子中,malloc不是神奇的“正确工作的正确工具”,但对于更复杂的情况(例如在运行时创建任意大小的数组),它是唯一的出路。

答案 3 :(得分:6)

char *some_memory = "Hello World";
sprintf(some_memory, "Goodbye...");

是非法的,字符串文字是const

这将在堆栈上或全局分配一个12字节的char数组(取决于它声明的位置)。

char some_memory[] = "Hello World";

如果要为进一步操作留出空间,可以指定数组的大小应该更大。 (但请不要在堆栈上放1MB。)

#define LINE_LEN 80

char some_memory[LINE_LEN] = "Hello World";
strcpy(some_memory, "Goodbye, sad world...");
printf("%s\n", some_memory);

答案 4 :(得分:6)

如果您不知道需要使用的内存的确切大小,则需要动态分配(malloc)。一个示例可能是用户在您的应用程序中打开文件。您需要将文件的内容读入内存,但当然您不会提前知道文件的大小,因为用户在运行时会在现场选择文件。因此,如果您事先不知道正在使用的数据大小,那么基本上您需要malloc。至少这是使用malloc的主要原因之一。在您的示例中,您已经知道编译时的大小(并且您不想修改它)的简单字符串,动态分配它没有多大意义。

稍微偏离主题,但是......在使用malloc时,必须非常小心不要创建内存泄漏。请考虑以下代码:

int do_something() {
    uint8_t* someMemory = (uint8_t*)malloc(1024);

    // Do some stuff

    if ( /* some error occured */ ) return -1;

    // Do some other stuff

    free(someMemory);
    return result;
}

你看到这段代码出了什么问题吗? mallocfree之间有一个条件返回语句。一开始看起来似乎还可以,但请想一想。如果出现错误,您将返回而不释放您分配的内存。这是内存泄漏的常见原因。

当然这是一个非常简单的例子,在这里很容易看到错误,但想象数百行代码散布着指针,malloc s,free和各种各样的代码错误处理。事情真的很快就会变得非常混乱。这是在适用的情况下我更喜欢现代C ++而不是C的原因之一,但这是一个完整的主题。

因此,无论何时使用malloc,请始终确保您的记忆尽可能free

答案 5 :(得分:5)

需要分配内存的一个原因是,如果要在运行时修改它。在这种情况下,可以使用堆栈上的malloc或缓冲区。将“Hello World”分配给指针的简单示例定义了“通常”在运行时无法修改的内存。