Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Linux内存管理开销_C++_Linux_Memory - Fatal编程技术网

C++ Linux内存管理开销

C++ Linux内存管理开销,c++,linux,memory,C++,Linux,Memory,我试图解释在Linux中应用程序的内存。我做了一个基本的测试,发现如果我们增加一些内存,它会为一个新的内存分配至少32个字节 这是我的密码 #include <iostream> #include <stdlib.h> using namespace std; int main(int argc, const char** argv) { int iBlockSize = atoi(argv[1]); int iBlockCount =

我试图解释在Linux中应用程序的内存。我做了一个基本的测试,发现如果我们增加一些内存,它会为一个新的内存分配至少32个字节

这是我的密码

#include <iostream>
#include <stdlib.h>

using namespace std;

int main(int argc, const char** argv)
{
        int iBlockSize = atoi(argv[1]);
        int iBlockCount = atoi(argv[2]);

        for (int i = 0 ; i < iBlockCount ; i++)
        {
                cout << (int*)(new char[iBlockSize]) << endl;
        }
        return 0;
};
我得到的所有内存都有32个字节的间隔

直到24(块大小)都是一样的。如果超过24,则为48字节

/a.out 25 100

....
....
....
0x18b30c0
0x18b30f0
0x18b3120
0x18b3150
0x18b3180
0x18b31b0
0x18b31e0
0x18b3210
0x18b3240
0x18b3270
0x18b32a0
当我测试更大尺寸时;我们发现我们得到的内存增加了16字节块,保持了至少8字节的开销

我的问题是,

  • 我的测试正确吗
  • 这是linux内存管理的正确行为吗
  • 如果我们增加8个字节,我们得到32个。另外24个怎么了?重复使用或分解开销

  • 类C语言中的内存分配必须为所有基元类型返回适当对齐的内存[0]。 这意味着内存分配通常会为您提供至少8字节对齐的内存,以便您可以在其中存储双倍的

    因此,当您请求1字节的内存时,由于对齐要求,您将至少使用8字节。 在64位系统上,内存分配通常为您提供16字节对齐内存,因为这些系统通常具有16字节大类型(SSE向量)

    此外,内存分配器需要一些空间来存放其管理数据,如分配的大小。 根据实现情况,这些数据可以放在用户分配的内存块之前或之后


    [P>(0)当地址/指针是访问的大小的倍数时,内存对齐,一些CPU不支持未对齐的访问(例如SPARC),其他(如x86)如果这样做,则会有性能惩罚。

    <>与主题相关的C++标准的几行;我认为它简单地描述了这不是错误的行为

    < >在C++程序中定义的任何分配和/或解除分配函数, 包括库中的默认版本,应符合 3.7.4.1和3.7.4.2中规定的语义

    3.7.4.1分配功能。。。返回的指针应适当对齐,以便可以转换为任何类型的指针 具有基本对齐要求的完整对象类型(3.11) 而且

    3.11对齐对象类型具有对齐要求(3.9.1、3.9.2),这些要求对可分配该类型对象的地址进行了限制。对齐是定义的实现 一个整数值,表示连续数据之间的字节数 可以分配给给定对象的地址

    我找到了这篇文章

    它说“如果数据将通过向量指令加载和存储进行访问,请在16字节边界上对齐数据。”


    因此,看起来这是glibc做出的调整决策,每次分配都会有开销。分配数组通常需要将大小存储在某个位置,通常存储在数据本身附近。感谢jtaylor的解释。无论如何,如果内存元数据(管理数据)也保持在同一位置。如果我们错误地写了越界,这会影响内存管理模块吗?我用新字符分配的整个32字节的memset测试了相同的代码[8]。然后程序在delete[]处崩溃(***glibc检测到***./a.out:free():无效的下一个大小(fast):0x0000000000603fa0***)并且不在memset中。这说明内存管理数据也与内存本身保持一致。如果删除delete[],即使分配和写入千兆字节的内存,程序运行也不会出现任何错误。保存管理数据的位置是一个实现细节,并且会根据您使用的malloc进行更改。例如,glibc具有特殊的malloc调试标志(例如默认情况下经常启用malloc_CHECK_),这将导致glibc检查其内部数据的不一致性,这就是为什么在delete上看到崩溃,而在memset上看不到。
    ....
    ....
    ....
    0x18b30c0
    0x18b30f0
    0x18b3120
    0x18b3150
    0x18b3180
    0x18b31b0
    0x18b31e0
    0x18b3210
    0x18b3240
    0x18b3270
    0x18b32a0