当前位置: 首页 > 知识库问答 >
问题:

奇怪的C++内存分配

狄誉
2023-03-14

我用C++创建了一个简单的类Storer,用于内存分配。它包含六个字段变量,所有这些变量都在构造函数中赋值:

int x;
int y;
int z;
char c;
long l;
double d;

我对这些变量是如何存储的很感兴趣,所以我编写了以下代码:

Storer *s=new Storer(5,4,3,'a',5280,1.5465);
cout<<(long)s<<endl<<endl;
cout<<(long)&(s->x)<<endl;
cout<<(long)&(s->y)<<endl;
cout<<(long)&(s->z)<<endl;
cout<<(long)&(s->c)<<endl;
cout<<(long)&(s->l)<<endl;
cout<<(long)&(s->d)<<endl;

我对输出非常感兴趣:

33386512

33386512
33386516
33386520
33386524
33386528
33386536
cout<<sizeof(s->c)<<endl;
cout<<sizeof(Storer)<<endl;
cout<<sizeof(int)+sizeof(int)+sizeof(int)+sizeof(char)+sizeof(long)+sizeof(double)<<endl;
1
32
29

共有1个答案

微生自怡
2023-03-14

数据对齐和编译器填充打招呼!

CPU没有类型的概念,它在32位(或64位、128位(SSE)或256位(AVX)中得到了什么--让我们简单地保持32)寄存器需要正确地对齐,以便正确有效地处理。想象一个简单的场景,您有一个char,后面跟着一个int。在32位体系结构中,字符为1字节,整数为4字节。

一个32位寄存器必须打破它的边界,只接受3个字节的整数,并将第4个字节留给“第二次运行”。它不能以这种方式正确地处理数据,所以编译器将添加填充以确保所有的东西都得到有效的处理。这意味着根据所讨论的类型添加一定量的填充。

阅读更多关于数据对齐的信息,当您处理诸如SSE(128位regs)或AVX(256位regs)之类的指令集扩展时,数据对齐非常方便,因此必须特别小心,以便不会破坏向量化的优化(对于SSE在16字节边界上对齐,16*8->128位)。

phonetagger在评论中提出了一个有效的观点,即存在可以通过预处理器分配的pragma指令,以强制编译器以用户和程序员指定的方式对齐数据。但是像#pragma pack(...)这样的指令是对编译器的一个声明,说明您知道自己在做什么,什么对您最好。一定要这样做,因为如果您不能适应您的环境,您可能会经历各种惩罚--最明显的是使用您没有自己编写的外部库,这些库在打包数据的方式上有所不同。

事情发生冲突就会爆炸。最好的建议是在这种情况下要谨慎,并真正与手头的问题密切相关。如果你不确定,就把它留给默认值吧。如果您不确定,但必须使用SSE这样的方法,其中对齐是最重要的(不是默认的,也不是简单的),请在线查阅各种资源或在这里询问另一个问题。

 类似资料:
  • 这是个模糊的问题。因此,请随时询问任何具体数据。 我们有一个tomcat服务器,运行两个web服务。一个tomcat使用spring构建。90%的任务使用mysql,JSON缓存使用mongo(10%)。另一个web服务是使用grails编写的。这两项服务都是中等大小的代码库(每项约35k行代码) 计算仅在有HTTP请求(无批处理)时发生。每个请求大约有2000个数据库点击率(我知道它非常庞大,我

  • 有时,我的应用程序在启动时会随机出现故障,它会在应用程序类中崩溃,用户无法再次打开应用程序,直到他们进入设置并清除应用程序数据 “DiskbasedBache”试图分配超过1GB的内存,原因并不明显 我怎么才能让这一切不发生?这似乎是Volley的一个问题,或者是一个基于自定义磁盘的缓存的问题,但是我没有立即看到(从堆栈跟踪中)如何‘清除’这个缓存,或者做一个条件检查或者处理这个异常 欣赏洞察力

  • 我有一个ui显示的数据表:repeat。因为我希望用户能够在每行的基础上更改数据,所以每行都包含在一个h:form中。最后,每个h:form都有一个带有f:ajax标记的按钮。我的行为越来越不一致。 上述方法可行,但带宽显然不便宜。 如果我将render=“@all”更改为render=“@form”,Firebug显示发送的部分响应正常,但我的浏览器(Firefox)神秘地没有显示它。所以我猜它

  • 我在Chrome Developer Tools中出现这个错误已经有一段时间了,我似乎就是找不到不安全的http://请求。它指向我的域,但没有https://。http://www.example.com/不是一个脚本,所以我不明白它是从哪里来的。 内容混杂:“HTTPS://www.example.com/categoy/a-product.html”页面是通过HTTPS加载的,但请求的脚本“

  • 这个程序打印00,但是如果我注释掉a.store和b.store,而取消注释a.fetch_add和b.fetch_add,这做了完全相同的事情,即都设置了a=1,b=1的值,我永远不会得到00。 是我错过了什么,还是“00”按标准永远不会出现? 下面打印00。 下图从不打印00 再看看这个,多线程原子a b打印00 for memory_order_refield

  • 索引0数组列表的预期输出是名称和数字。但它显示出奇怪的结果为什么? 完整代码在这里输入图像描述在这里