我应该什么时候用C语言的malloc,什么时候用?

时间:2022-09-20 13:58:15

I understand how malloc() works. My question is, I'll see things like this:

我理解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);

I omitted error checking for the sake of brevity. My question is, can't you just do the above by initializing a pointer to some static storage in memory? perhaps:

为了简洁起见,我省略了错误检查。我的问题是,你不能通过初始化一个指向内存中的静态存储的指针来完成上述操作吗?可能:

char *some_memory = "Hello World";

At what point do you actually need to allocate the memory yourself instead of declaring/initializing the values you need to retain?

在什么情况下,您实际上需要自己分配内存,而不是声明/初始化您需要保留的值?

6 个解决方案

#1


117  

char *some_memory = "Hello World";

is creating a pointer to a string constant. That means the string "Hello World" will be somewhere in the read-only part of the memory and you just have a pointer to it. You can use the string as read-only. You cannot make changes to it. Example:

正在创建一个指向字符串常量的指针。这意味着字符串“Hello World”将位于内存的只读部分,而您只是有一个指向它的指针。您可以使用该字符串作为只读。你不能改变它。例子:

some_memory[0] = 'h';

Is asking for trouble.

是在自找麻烦。

On the other hand

另一方面

some_memory = (char *)malloc(size_to_allocate);

is allocating a char array ( a variable) and some_memory points to that allocated memory. Now this array is both read and write. You can now do:

分配一个char数组(一个变量)和some_memory指向那个分配的内存。这个数组既可以读也可以写。你现在可以做的事:

some_memory[0] = 'h';

and the array contents change to "hello World"

数组内容改为hello World

#2


27  

For that exact example, malloc is of little use.

对于这个例子,malloc没有什么用处。

The primary reason malloc is needed is when you have data that must have a lifetime that is different from code scope. Your code calls malloc in one routine, stores the pointer somewhere and eventually calls free in a different routine.

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

A secondary reason is that C has no way of knowing whether there is enough space left on the stack for an allocation. If your code needs to be 100% robust, it is safer to use malloc because then your code can know the allocation failed and handle it.

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

#3


14  

malloc is a wonderful tool for allocating, reallocating and freeing memory at runtime, compared to static declarations like your hello world example, which are processed at compile-time and thus cannot be changed in size.

malloc是一个在运行时分配、重新分配和释放内存的好工具,与像hello world示例这样的静态声明相比,它是在编译时处理的,因此不能更改大小。

Malloc is therefore always useful when you deal with arbitrary sized data, like reading file contents or dealing with sockets and you're not aware of the length of the data to process.

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

Of course, in a trivial example like the one you gave, malloc is not the magical "right tool for the right job", but for more complex cases ( creating an arbitrary sized array at runtime for example ), it is the only way to go.

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

#4


5  

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

is illegal, string literals are const.

是非法的,字符串文字是常量。

This will allocate a 12-byte char array on the stack or globally (depending on where it's declared).

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

char some_memory[] = "Hello World";

If you want to leave room for further manipulation, you can specify that the array should be sized larger. (Please don't put 1MB on the stack, though.)

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

#define LINE_LEN 80

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

#5


4  

One reason when it is necessary to allocate the memory is if you want to modify it at runtime. In that case, a malloc or a buffer on the stack can be used. The simple example of assigning "Hello World" to a pointer defines memory that "typically" cannot be modified at runtime.

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

#6


3  

If you don't know the exact size of the memory you need to use, you need dynamic allocation (malloc). An example might be when a user opens a file in your application. You will need to read the file's contents into memory, but of course you don't know the file's size in advance, since the user selects the file on the spot, at runtime. So basically you need malloc when you don't know the size of the data you're working with in advance. At least that's one of the main reasons for using malloc. In your example with a simple string that you already know the size of at compile time (plus you don't want to modify it), it doesn't make much sense to dynamically allocate that.

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


Slightly off-topic, but... you have to be very careful not to create memory leaks when using malloc. Consider this code:

有点跑题,但是……在使用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;
}

Do you see what's wrong with this code? There's a conditional return statement between malloc and free. It might seem okay at first, but think about it. If there's an error, you're going to return without freeing the memory you allocated. This is a common source of memory leaks.

您知道这段代码有什么问题吗?malloc和free之间有一个条件返回语句。一开始可能看起来还行,但想想吧。如果出现错误,您将在不释放分配的内存的情况下返回。这是内存泄漏的常见来源。

Of course this is a very simple example, and it's very easy to see the mistake here, but imagine hundreds of lines of code littered with pointers, mallocs, frees, and all kinds of error handling. Things can get really messy really fast. This is one of the reasons I much prefer modern C++ over C in applicable cases, but that's a whole nother topic.

当然,这是一个非常简单的例子,很容易看到这里的错误,但是想象一下数百行代码,其中充斥着指针、错误、释放和各种错误处理。事情会很快变得一团糟。这是我在适用的情况下更喜欢c++的原因之一,但这是一个完全不同的话题。

So whenever you use malloc, always make sure your memory is as likely to be freed as possible.

因此,无论何时使用malloc,总是要确保尽可能释放内存。

#1


117  

char *some_memory = "Hello World";

is creating a pointer to a string constant. That means the string "Hello World" will be somewhere in the read-only part of the memory and you just have a pointer to it. You can use the string as read-only. You cannot make changes to it. Example:

正在创建一个指向字符串常量的指针。这意味着字符串“Hello World”将位于内存的只读部分,而您只是有一个指向它的指针。您可以使用该字符串作为只读。你不能改变它。例子:

some_memory[0] = 'h';

Is asking for trouble.

是在自找麻烦。

On the other hand

另一方面

some_memory = (char *)malloc(size_to_allocate);

is allocating a char array ( a variable) and some_memory points to that allocated memory. Now this array is both read and write. You can now do:

分配一个char数组(一个变量)和some_memory指向那个分配的内存。这个数组既可以读也可以写。你现在可以做的事:

some_memory[0] = 'h';

and the array contents change to "hello World"

数组内容改为hello World

#2


27  

For that exact example, malloc is of little use.

对于这个例子,malloc没有什么用处。

The primary reason malloc is needed is when you have data that must have a lifetime that is different from code scope. Your code calls malloc in one routine, stores the pointer somewhere and eventually calls free in a different routine.

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

A secondary reason is that C has no way of knowing whether there is enough space left on the stack for an allocation. If your code needs to be 100% robust, it is safer to use malloc because then your code can know the allocation failed and handle it.

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

#3


14  

malloc is a wonderful tool for allocating, reallocating and freeing memory at runtime, compared to static declarations like your hello world example, which are processed at compile-time and thus cannot be changed in size.

malloc是一个在运行时分配、重新分配和释放内存的好工具,与像hello world示例这样的静态声明相比,它是在编译时处理的,因此不能更改大小。

Malloc is therefore always useful when you deal with arbitrary sized data, like reading file contents or dealing with sockets and you're not aware of the length of the data to process.

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

Of course, in a trivial example like the one you gave, malloc is not the magical "right tool for the right job", but for more complex cases ( creating an arbitrary sized array at runtime for example ), it is the only way to go.

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

#4


5  

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

is illegal, string literals are const.

是非法的,字符串文字是常量。

This will allocate a 12-byte char array on the stack or globally (depending on where it's declared).

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

char some_memory[] = "Hello World";

If you want to leave room for further manipulation, you can specify that the array should be sized larger. (Please don't put 1MB on the stack, though.)

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

#define LINE_LEN 80

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

#5


4  

One reason when it is necessary to allocate the memory is if you want to modify it at runtime. In that case, a malloc or a buffer on the stack can be used. The simple example of assigning "Hello World" to a pointer defines memory that "typically" cannot be modified at runtime.

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

#6


3  

If you don't know the exact size of the memory you need to use, you need dynamic allocation (malloc). An example might be when a user opens a file in your application. You will need to read the file's contents into memory, but of course you don't know the file's size in advance, since the user selects the file on the spot, at runtime. So basically you need malloc when you don't know the size of the data you're working with in advance. At least that's one of the main reasons for using malloc. In your example with a simple string that you already know the size of at compile time (plus you don't want to modify it), it doesn't make much sense to dynamically allocate that.

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


Slightly off-topic, but... you have to be very careful not to create memory leaks when using malloc. Consider this code:

有点跑题,但是……在使用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;
}

Do you see what's wrong with this code? There's a conditional return statement between malloc and free. It might seem okay at first, but think about it. If there's an error, you're going to return without freeing the memory you allocated. This is a common source of memory leaks.

您知道这段代码有什么问题吗?malloc和free之间有一个条件返回语句。一开始可能看起来还行,但想想吧。如果出现错误,您将在不释放分配的内存的情况下返回。这是内存泄漏的常见来源。

Of course this is a very simple example, and it's very easy to see the mistake here, but imagine hundreds of lines of code littered with pointers, mallocs, frees, and all kinds of error handling. Things can get really messy really fast. This is one of the reasons I much prefer modern C++ over C in applicable cases, but that's a whole nother topic.

当然,这是一个非常简单的例子,很容易看到这里的错误,但是想象一下数百行代码,其中充斥着指针、错误、释放和各种错误处理。事情会很快变得一团糟。这是我在适用的情况下更喜欢c++的原因之一,但这是一个完全不同的话题。

So whenever you use malloc, always make sure your memory is as likely to be freed as possible.

因此,无论何时使用malloc,总是要确保尽可能释放内存。