malloc的知识点学习


=Start=

缘由:

周末闲来无事,深入学习、整理一下malloc/calloc的知识

正文:

参考解答:
Why does malloc initialize the values to 0 in gcc?

简而言之:

没有,只不过在你的例子中它恰好是零。

并且,你的测试用例并没有显示(所有的)数据都为0。它只显示了一个元素是否为0。


复杂一些的解释:

当你调用malloc()时,有两件事会发生

  1. 它从同一个进程之前分配和释放的内存中进行回收后再分配;
  2. 它向操作系统申请新的内存页;

在第一种情况下,申请的内存中将包含以前分配中剩余的数据。所以它不会是零。这是执行小块内存分配时的常见情形。

在第二种情况下,申请的内存来自于操作系统。当程序耗尽内存时,或者当你请求一个非常大块内存的分配时,就会发生这种情况。(在你的例子中也是如此)

这里就有一个问题:出于安全考虑,来自操作系统的内存将被归零

当操作系统给你分配内存时,内存可能是从不同的进程中释放出来的。因此,内存在可能会包含敏感信息,比如密码。为了防止你读取这些数据,操作系统会在它给你之前将它归零。

*我注意到,C标准在并没有说明这一点。这是严格的操作系统行为。因此,这个归零操作可能不存在于安全不受关注的系统中。


为了提供更多和性能相关的背景知识:

正如 @R. 在评论中提到的,这个归零操作就是为什么你应该总是使用calloc()而不是malloc()+memset()组合。因为calloc()可以利用这个事实来避免单独的memset()。


不过另一方面,这种归零操作有时会是性能瓶颈。在一些数值应用程序中(比如不存在的FFT),你需要分配大量的scratch内存。使用它执行任何算法,然后释放它。

在这些情况下,归零操作是不必要的,并且是纯粹的开销。

我所见过的最极端的例子是,在70秒的操作中花费了20秒的时间对48 GB的缓冲区进行归零操作。(大约30%的开销)(当然,这台机器确实缺少内存带宽。)

最明显的解决方案是简单地手动重用内存。但这通常需要打破已经建立的接口。(特别是如果它是库例程的一部分)


malloc() allocates size bytes and returns a pointer to the allocated memory.
The memory is not cleared. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

Difference between malloc and calloc?(malloc和calloc的不同之处)
// void *malloc(size_t size);
ptr = (char **) malloc (MAXELEMS * sizeof(char *));

// void *calloc(size_t nmemb, size_t size);
ptr = (char **) calloc (MAXELEMS, sizeof(char*));

calloc()会用零初始化缓冲区,而malloc()则未将内存初始化。

归零操作可能需要花费一些时间,因此如果性能是一个问题,那么你可能需要使用malloc()。如果初始化内存更重要,请使用calloc()。比如,用了calloc()你就不需要在malloc()之外再调用memset()。


Does malloc lazily create the backing pages for an allocation on Linux (and other platforms)?

Linux确实延迟了页面(内存)分配,也就是「乐观的内存分配」。从malloc返回的内存没有任何东西支持,当你使用它时,你可能会碰到一个OOM状况(如果你请求的页面没有交换空间),在这种情况下,进程会被随意终止

可以去 http://www.linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html 看实际例子。


什么时候该使用malloc?(When to use malloc for char pointers

当你需要 创建/格式化 一个新字符串时,就应该使用malloc(然后要记得free);如果只是简单的指向一个字符串,并不需要用malloc在字符串指针上。


是否有必要在malloc()之后显示调用memset()对申请的内存进行初始化操作?(Do I have to memset after malloc new memory?

malloc不会对由它分配的内存进行初始化操作。所以,你得到的内容里面的数据是随机的。如果你真的需要将一切设置为0,那么就使用在性能上有一定损耗的calloc来实现。(如果你需要初始化为非0的内容,那么可以使用memset对字节数组进行初始化其它类型的就需要手动对数组进行循环来初始化它。)


对内存进行归零操作(zeroing out memory
// first choice
char buffer[1024] = {0};

// second choice
char buffer[1024];
memset(buffer, 0, sizeof(buffer));

// second.2 choice
char *buffer;
buffer = malloc(sizeof(char) * 1024 );
if( buffer == NULL ) {
    /* Error management */
}
memset(buffer, 0, sizeof(char)*1024 );

// third choice
char *buffer;
buffer = calloc(sizeof(char), 1024 );
if( buffer == NULL ) {
    /* Error management */
}
参考链接:
  • 如上

=END=

, ,

《 “malloc的知识点学习” 》 有 6 条评论

  1. http://man7.org/linux/man-pages/man3/calloc.3.html
    Linux C 堆内存管理函数malloc()、calloc()、realloc()、free()详解
    http://www.cnblogs.com/phpgo/p/5794342.html
    `
    calloc()函数的第二个参数是「每个元素的大小」,并非初始化时填充的内容!calloc()函数得到的内存空间是经过初始化的,其内容全为0。
    calloc()函数有两个参数,分别为元素的个数和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。
    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注