C++ 对象数组的惰性分配

2024-01-10

如果我做类似的事情:

void f() {
    const int n = 1<<14;
    int *foo = new int [n];
}

or

void f() {
    const int n = 1<<14;
    int *foo = new int [n]();
}

Linux内核会使用惰性内存分配吗?对于第二种情况,与创建静态数组时的方式相同吗?

我能走多远?例如,有一个将用 0 填充的结构,它会始终被延迟分配,还是会在初始化时实际分配物理 RAM?

struct X {
    int a, b, c, d, f, g, ..., z;
}

void f() {
    int *foo = new X();//lazy?
    const int n = 1<<14;
    int *foo = new X [n]();//lazy?
}

对于运行 Linux 5.4.0-51-generic 的标准 Ubuntu 20.04 机器...

我们可以直接观察这一点。在下面的代码中,我增加了n价值1 << 24(约 1600 万int32 位 s = 64MBint)所以它是总体内存使用的主导因素。我编译、运行并观察了内存使用情况htop:

#include <unistd.h>
int main() {
    int *foo = new int [1 << 24];
    sleep(100);
}

htop 值:VIRT 71416KB / RES 1468KB

虚拟地址分配包括分配的内存new,但驻留内存大小要小得多 - 表明分配的所有 64MB 还不需要不同的物理后备内存页面。


更改为后int *foo = new int[1<<24]();:

htop 值:VIRT 71416KB / RES 57800KB

请求内存清零会导致驻留内存值略低于初始化的 64MB,这并不是由于内存压力(我有 64GB RAM),但内核中的某些算法必须决定分页出一些内存归零后的后备存储器(我怀疑kswapd?)。大 RES 值表明每个归零页都被赋予了物理后备内存的不同页(与例如映射到操作系统的零页以进行实际后备页的 COW 分配不同)。


与结构:

#include <unistd.h>

struct X {
    int a[1 << 24];
};

int main() {
    auto foo = new X;
    sleep(100);
}

htop 值:VIRT 71416KB / RES 1460KB

这表明静态数组的 RES 不足以具有不同的支持页面。虚拟内存要么已预先映射到操作系统零页,要么未映射,并且在访问时最初会映射到零页,然后在写入时给出其自己的物理支持页 - 我不确定是哪一个,但就实际物理 RAM 使用情况而言,它没有任何区别。


更改为后auto foo = new X{};

htop 值:VIRT 71416KB / RES 67844KB


您可以清楚地看到,将字节初始化为 0 导致使用数组的后备内存。

解决您的问题:

Linux内核会使用惰性内存分配吗?

虚拟内存分配完成时new已经完成了。当用户空间代码对内存进行实际写入时,会延迟分配不同的物理后备内存。

对于第二种情况,与创建静态数组时的方式相同吗?

#include <unistd.h>

int g_a[1 << 24];

int f(int i) {
    static int a[1 << 24];
    return a[i];
}

int main(int argc, const char* argv[]) {
    sleep(20);
    int k = f(2930);
    sleep(20);
    return argc + k;
}

VIRT 133MB分辨率 1596KB

运行时,内存didn't20秒后跳转,说明程序加载时虚拟地址空间全部分配完毕。低常驻内存表明页面已not按原来的方式访问和归零new.

只是为了解决一个潜在的混乱点:虽然 Linux 内核会在第一次向进程提供后备内存时将其清零,但任何给定的调用new(在我见过的任何实现中)不会知道分配的内存是否是从早期的动态分配中回收的 - 可能已写入非零值 - 从那以后deleted/freed.因此,如果您使用内存清零形式,例如new X{} or new int[n]()那么内存将被用户空间代码无条件地清除,导致全部的后备内存被分配并出现故障。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 对象数组的惰性分配 的相关文章

  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐