当前位置: 首页 > 面试题库 >

为什么malloc在gcc中将值初始化为0?

公冶高峯
2023-03-14
问题内容

平台之间可能有所不同,但是

当我使用gcc编译并运行下面的代码时,每次在ubuntu 11.10中获得0。

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

int main()
{
    double *a = (double*) malloc(sizeof(double)*100)
    printf("%f", *a);
}

为什么即使有calloc,malloc的行为也是如此?

难道就意味着即使您不希望有时将值初始化为0,也会有不必要的性能开销吗?

编辑:哦,我以前的示例不是初始化,而是碰巧使用“新鲜”块。

我恰恰在寻找的是为什么它在分配一个大块时将其初始化:

int main()
{
    int *a = (int*) malloc(sizeof(int)*200000);
    a[10] = 3;
    printf("%d", *(a+10));

    free(a);

    a = (double*) malloc(sizeof(double)*200000);
    printf("%d", *(a+10));
}

OUTPUT: 3
        0 (initialized)

但是,感谢您指出进行分配时存在安全原因!(从来没有想过)。确保在分配新鲜块或大块时必须将其初始化为零。


问题答案:

简短答案:

并非如此,在您的情况下恰好为零。
(此外,您的测试用例不会显示数据为零。仅显示一个元素为零的情况。)

长答案:

当您致电时malloc(),将发生以下两种情况之一:

  1. 它回收先前分配的内存并从同一进程中释放出来。
  2. 它从操作系统请求新页面。

在第一种情况下,内存将包含以前分配剩余的数据。因此它不会为零。这是执行小分配时的通常情况。

在第二种情况下,内存将来自操作系统。当程序内存不足时或在请求大量分配时,会发生这种情况。(例如您的示例)

问题在于: 出于 安全 原因,来自操作系统的内存将被清零。*

当操作系统为您提供内存时,它可能已从其他进程中释放出来。这样,内存可以包含敏感信息,例如密码。因此,为防止您读取此类数据,操作系统会在将数据提供给您之前将其清零。

*我注意到C标准对此没有说明。严格来说,这是一种操作系统行为。因此,在不考虑安全性的系统上,可能会或可能不会出现这种调零。

要为此提供更多的性能背景:

作为@R。在评论中提到,此归零是为什么您应始终使用calloc()而不是malloc()+的原因memset()calloc()可以利用这个事实来避免单独使用memset()

另一方面,这种归零有时是性能瓶颈。在某些数字应用程序中(例如,不适当的FFT),您需要分配大量的暂存存储器。使用它执行任何算法,然后释放它。

在这些情况下,归零是不必要的,并且完全是开销。

我看到的最极端的示例是使用48 GB暂存缓冲区进行70秒的操作需要20秒的清零开销。(大约30%的开销。) (保证:机器确实没有内存带宽。)

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



 类似资料:
  • 我使用的是一个简单的客户端 普罗米修斯 版本 0.6.0 我有一组以这种方式定义的计数器 我将这个类注入到我需要它的地方,然后调用addCdProductVicessCreated()等方法,但对于没有值的指标,当我抓取它们时,它们看起来是空的,例如: 我的问题是如何初始化值为0的计数器,以便即使未调用inc方法也能显示出来

  • 问题内容: 我有这个代码: 这会导致编译错误:可能尚未初始化,这很公平。 现在,我将代码更改为: 我得到同样的编译错误!我必须初始化为null: 那么,不初始化对象和初始化为null有什么区别?如果我声明一个没有初始化的对象,它是否为null? 谢谢 问题答案: 字段(成员变量)被初始化为(或初始化为默认的原始值,如果它们是原始的) 局部变量未初始化,您有责任设置初始值。

  • 本文向大家介绍为什么要初始化 CSS 样式相关面试题,主要包含被问及为什么要初始化 CSS 样式时的应答技巧和注意事项,需要的朋友参考一下 因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对 CSS 初始化往往会出现浏览器之间的页面显示差异。 当然,初始化样式会对 SEO 有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。 最简单的初始化方法是:*{padding:

  • LeetCode 43题字符串相乘,乘好后的结果无法放入数组,且初始化并不成功,每次想将数组初始化的时候都会报错。 尝试了用calloc,memset,for循环对数组进行初始化,但是都失败了,直接定义进行初始化也不行,不知道是什么原因? 题目描述: 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 注意:不能使用任何

  • 为什么x没有在下面初始化? 平均而言,对于一半的迭代,for循环中的将是,从而初始化。对于另一半,找到的 循环替换为 同样糟糕。只有