【问题标题】:Memory allocation in OS操作系统中的内存分配
【发布时间】:2017-07-11 06:57:43
【问题描述】:

用 C++ 编写这个简单的代码:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class Empty{};

int main() {
    array<unique_ptr<Empty>, 1024> empties;

    for(size_t i =0; i < 1024; i++){
        empties[i] = make_unique<Empty>();
    }

    for(auto& element : empties){
        cout << "ptr: " << element.get() << endl;
    }

    return 0;
}

在 ideone.com 或 Windows 中运行时,我们得到以下结果:

ptr: 0x2b601f0c9ca0
ptr: 0x2b601f0c9cc0
ptr: 0x2b601f0c9ce0
ptr: 0x2b601f0c9d00
ptr: 0x2b601f0c9d20
ptr: 0x2b601f0c9d40
ptr: 0x2b601f0c9d60 ...

对我来说这很奇怪。操作系统或标准库中什么样的分配算法可能会导致地址没有分配,其结尾的数字不是0?

我做这个实验的原因是,鉴于操作系统使用伙伴算法,管理页面和分配请求将导致操作系统分配一块连续的内存,然后分配几个下一个分配(直到用完分配的内存)应该分配在附近。如果是这样的话,那么在某些情况下,列表的缓存问题可能不会那么重要,但我得到了我没想到的结果。

分配节点中从右数第二个数字也是完全随机的。什么可能导致这种行为?

【问题讨论】:

  • 我不知道您使用的是什么操作系统,但至少 Linux 将所有堆分配对齐为 16 字节。一些像 llvm 团队这样狡猾的人实际上使用这个事实来存储那些总是零位的东西。
  • 操作系统本身与此无关。操作系统分配页面,程序的分配器(可能来自您动态链接到的标准库,可能随操作系统提供,但不是操作系统本身)将页面细分为分配的块。它可能需要一些空间用于跟踪信息,出于效率/碎片相关原因对齐分配等。空分配成本 32 字节并非不合理/闻所未闻。
  • 即使结构是空的,它仍然需要有一个可寻址的大小。添加到该大小的将是系统分配器对齐和填充。
  • 连续指针值之差为 32(字节)。这不是“完全随机的”。看起来很正常,符合我的预期。
  • @SanderDeDycker 对我来说预计是 8 个字节,因为它是可寻址单元的最小化

标签: c++ c++11 memory memory-management dynamic-memory-allocation


【解决方案1】:

如果我没记错的话,C++ 中类的最小大小是一个字节。由于类之间存在一致的 32 字节间距,因此这可能恰好是您创建的空类的大小。要确定这一点,请尝试添加

std::cout << "Empty class size: " << sizeof(Empty) << std::endl;

它可能不会是 32 字节,相反,每个对象之间可能会有一些一致的间距。

注意: 这是否为您编译。它不适合我,因为空不能被隐式初始化。

【讨论】:

  • 是的 :) ideone.com/9lWs7Z。初始化应该没有问题,因为 unique_ptr 有默认构造函数。
  • 嗯。这很奇怪。将 clang 与 --std=c++14 一起使用,然后使用 IDK。
  • 请参考上面评论中给出的链接以获得提示:)
【解决方案2】:

请注意打印的指针不准确,当它们可以分配到完全不同的页面时,操作系统允许您将它们视为后续指针。

【讨论】:

  • 为什么要分配到不同的页面?
  • 你在说什么操作系统?
  • Windows 操作系统,但我想 Linux 上也会发生同样的情况
  • @DawidPi 我实际上是在问 user2733996 :)
  • 您指的是虚拟地址还是物理地址?物理地址没有任何意义。
猜你喜欢
  • 2016-08-06
  • 1970-01-01
  • 2021-10-16
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 2018-08-15
  • 1970-01-01
  • 2012-07-09
相关资源
最近更新 更多