我理解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";
你真的需要自己分配内存而不是声明/初始化你需要保留的值?
答案 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)
当然,在你给出的一个简单的例子中,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;
}
你看到这段代码出了什么问题吗? malloc
和free
之间有一个条件返回语句。一开始看起来似乎还可以,但请想一想。如果出现错误,您将返回而不释放您分配的内存。这是内存泄漏的常见原因。
当然这是一个非常简单的例子,在这里很容易看到错误,但想象数百行代码散布着指针,malloc
s,free
和各种各样的代码错误处理。事情真的很快就会变得非常混乱。这是在适用的情况下我更喜欢现代C ++而不是C的原因之一,但这是一个完整的主题。
因此,无论何时使用malloc
,请始终确保您的记忆尽可能free
。
答案 5 :(得分:5)
需要分配内存的一个原因是,如果要在运行时修改它。在这种情况下,可以使用堆栈上的malloc或缓冲区。将“Hello World”分配给指针的简单示例定义了“通常”在运行时无法修改的内存。