Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.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++ malloc如何理解对齐?_C++_C_Memory Alignment - Fatal编程技术网

C++ malloc如何理解对齐?

C++ malloc如何理解对齐?,c++,c,memory-alignment,C++,C,Memory Alignment,以下摘自 分配原始存储。实际上,malloc调用分配存储 它足够大并且适当对齐以容纳类型为的对象 小部件 从赫伯·萨特身上也可以看出,他说: 对齐。任何内存对齐。任何分配的内存 通过new或malloc动态,保证正确对齐 任何类型的对象,但不是动态分配的缓冲区 没有这样的保证 我对此很好奇,malloc如何知道自定义类型的对齐方式?malloc()可以使用的唯一信息是传递给它的请求的大小。通常,它可能会将传递的大小四舍五入到最接近的2的更大(或相等)次方,并根据该值对齐内存。对齐值也可能有一个上

以下摘自

分配原始存储。实际上,malloc调用分配存储 它足够大并且适当对齐以容纳类型为的对象 小部件

从赫伯·萨特身上也可以看出,他说:

对齐。任何内存对齐。任何分配的内存 通过new或malloc动态,保证正确对齐 任何类型的对象,但不是动态分配的缓冲区 没有这样的保证


我对此很好奇,malloc如何知道自定义类型的对齐方式?

malloc()可以使用的唯一信息是传递给它的请求的大小。通常,它可能会将传递的大小四舍五入到最接近的2的更大(或相等)次方,并根据该值对齐内存。对齐值也可能有一个上限,例如8字节


上面是一个假设的讨论,实际的实现取决于您正在使用的机器体系结构和运行库。也许您的
malloc()
总是返回以8字节对齐的块,并且它不必做任何不同的事情。

我认为Herb Sutter引号中最相关的部分是我用粗体标记的部分:

对齐。任何内存对齐。通过new或malloc动态分配的任何内存都保证对任何类型的对象正确对齐,但未动态分配的缓冲区没有这样的保证

它不需要知道你想要什么类型,因为它可以为任何类型对齐。在任何给定的系统上,都有一个必要或有意义的最大对齐大小;例如,具有四字节字的系统可能最多有四字节对齐

这一点也通过以下部分内容得到了明确:

malloc()
calloc()
函数返回一个指针,指向为任何类型的变量适当对齐的分配内存

1) 对齐到所有路线中最不常用的倍数。e、 g.如果INT需要4字节对齐,但指针需要8字节对齐,则将所有内容分配给8字节对齐。这会使所有内容都对齐


2) 使用size参数确定正确的对齐方式。对于较小的大小,您可以推断类型,例如
malloc(1)
(假设其他类型的大小不是1)始终是字符。C++ <代码>新< /COD>具有类型安全的优点,因此总是可以这样做出对齐决定。

对齐要求是递归的:任何<代码>结构> <代码>的对齐方式只是它的任何成员的最大对齐方式,这是递归理解的。 例如,假设每个基本类型的对齐方式都等于其大小(通常情况下并不总是如此),

struct X{int;char;double;}
的对齐方式为
double
,它将被填充为double大小的倍数(例如4(int)、1(char)、3(padding)、8(double))。
结构Y{int;X;float;}
的对齐方式为
X
,最大的对齐方式为
double
Y
的对齐方式为:4(int)、4(padding)、16(X)、4(float)、4(padding)

(所有数字都只是示例,在您的机器上可能会有所不同。)

因此,通过将其分解为基本类型,我们只需要知道少数基本路线,其中有一条众所周知的最大路线。C++甚至定义了一个类型<代码> Max,Realthyt < /Cord>,它的对齐是最大的对齐。
malloc()
需要做的就是选择一个地址,该地址是该值的倍数。

在C++11之前,使用最大对齐(精确值未知)处理对齐非常简单,malloc/calloc仍然以这种方式工作。这意味着对于任何类型,malloc分配都是正确对齐的

根据标准,错误的对齐可能会导致未定义的行为,但我看到x86编译器非常慷慨,只会以较低的性能来惩罚

请注意,您还可以通过编译器选项或指令调整对齐方式。(例如,VisualStudio的pragma包)

但是当涉及到新的位置时,C++11为我们带来了新的关键字,称为alignofalignas。下面的一些代码显示了编译器最大对齐度大于1时的效果。下面的第一个新位置是自动良好的,但第二个位置不是

#include <iostream>
#include <malloc.h>
using namespace std;
int main()
{
        struct A { char c; };
        struct B { int i; char c; };

        unsigned char * buffer = (unsigned char *)malloc(1000000);
        long mp = (long)buffer;

        // First placment new
        long alignofA = alignof(A) - 1;
        cout << "alignment of A: " << std::hex << (alignofA + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofA)
        {
            mp |= alignofA;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex <<mp << endl;
        A * a = new((unsigned char *)mp)A;
        mp += sizeof(A);

        // Second placment new
        long alignofB = alignof(B) - 1;
        cout << "alignment of B: " <<  std::hex << (alignofB + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofB)
        {
            mp |= alignofB;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex << mp << endl;
        B * b = new((unsigned char *)mp)B;
        mp += sizeof(B);
}
#包括
#包括
使用名称空间std;
int main()
{
结构A{char c;};
结构B{int i;char c;};
无符号字符*缓冲区=(无符号字符*)malloc(1000000);
长mp=(长)缓冲区;
//新的第一个安抚
长对准A=对准(A)-1;

coutmalloc不知道它在分配什么,因为它的参数只是总大小。
它只是对齐到对任何对象都安全的对齐方式。

总之,
malloc
使用“最坏情况”对齐方式,因为它不知道更好的对齐方式。这是否意味着
calloc
可以更智能,因为它需要两个参数,对象的数量和单个对象的大小?可能。可能不是。你必须查看你的要找出运行库源。-1,抱歉。您的答案包括真相,但也包括虚假信息。这不是“可能,可能不是”的事情;它是专门记录的,以一种不依赖于大小的方式工作。(不知道为什么不。这样做似乎非常有意义。)我自己的问题的答案是否定的。我发现:memalign函数似乎有潜在的用处:参见ruakh的回答,所以malloc在任何给定的系统中都会使用最大对齐大小,对吗?任何类型的变量的含义是什么?它没有回答我的问题。是吗
#include <iostream>
#include <malloc.h>
using namespace std;
int main()
{
        struct A { char c; };
        struct B { int i; char c; };

        unsigned char * buffer = (unsigned char *)malloc(1000000);
        long mp = (long)buffer;

        // First placment new
        long alignofA = alignof(A) - 1;
        cout << "alignment of A: " << std::hex << (alignofA + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofA)
        {
            mp |= alignofA;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex <<mp << endl;
        A * a = new((unsigned char *)mp)A;
        mp += sizeof(A);

        // Second placment new
        long alignofB = alignof(B) - 1;
        cout << "alignment of B: " <<  std::hex << (alignofB + 1) << endl;
        cout << "placement address before alignment: " << std::hex << mp << endl;
        if (mp&alignofB)
        {
            mp |= alignofB;
            ++mp;
        }
        cout << "placement address after alignment : " << std::hex << mp << endl;
        B * b = new((unsigned char *)mp)B;
        mp += sizeof(B);
}