Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.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++ 在Microsoft VC++;_C++_Visual C++ - Fatal编程技术网

C++ 在Microsoft VC++;

C++ 在Microsoft VC++;,c++,visual-c++,C++,Visual C++,如果使用new[]表达式创建具有析构函数的对象数组, 阵列中的对象可能没有正确对齐 #include <stdint.h> #include <stdio.h> #pragma pack(8) struct A{ int64_t i; char dummy; ~A(){} }; int main(){ A* pa= new A[2]; printf("sizeof(A)= %d, pointer= %p", sizeof(A), pa); } #包

如果使用new[]表达式创建具有析构函数的对象数组, 阵列中的对象可能没有正确对齐

#include <stdint.h> #include <stdio.h> #pragma pack(8) struct A{ int64_t i; char dummy; ~A(){} }; int main(){ A* pa= new A[2]; printf("sizeof(A)= %d, pointer= %p", sizeof(A), pa); } #包括 #包括 #布拉格语套装(8) 结构A{ int64_t i; 模拟字符; ~A(){} }; int main(){ A*pa=新的A[2]; printf(“sizeof(A)=%d,指针=%p”,sizeof(A),pa); } (我使用VC++2010 express构建32位目标)

输出(在我的计算机上)为:

sizeof(A)=16指针=00344f4c (sizeof(A)=16表示编译器不支持A的对齐要求,并且结构用7个字节填充[edited:u alignof(A)还返回8])

我理解为什么会发生这种情况:new[]需要存储数组长度,并为此使用分配的内存的前4个字节,然后在没有适当填充的情况下分配数组本身

从实际的角度来看,这种行为肯定很糟糕, 但它是否符合标准

 printf("sizeof(A)= %d, pointer= %08x", sizeof(A), pa);
作为警告,当您要打印内存地址时,请使用
%p


%x
需要
无符号int
,其大小可能不同于指针的大小。

IIRC默认的压缩是字节对齐的,使用设置为另一个压缩,然后获得填充。(或#pragma pack(n))


编辑:仔细想想,我认为默认包装甚至在VS版本之间有所不同。标准保证内存正确对齐

我怀疑VisualStudio犯了如此基本的错误

目前我不明白你为什么认为它不一致

您是否试图建议将其与16字节边界对齐?
这不是标准所要求的。它可能只需要对齐到4字节边界

3.11校准[基本校准] 2基本对齐由小于或等于所有上下文中实现支持的最大对齐表示,该对齐等于alignof(std::max_align_t)(18.2)

因此,以下代码应打印出实现所需的最大对齐:

#include <iostream>
#include <cstddef>
#include <cstdalign>

int main()
{
        std::cout << alignof(std::max_align_t) << "\n";
}
#包括
#包括
#包括
int main()
{

std::cout如果
结构A
仅包含,您可以使用
对齐的\u malloc
(请参阅)。如果需要构造,您可以将其与
放置新的
操作符结合使用。类似于此(我没有Microsoft VC++,因此它可能无法编译):


删除它是一件痛苦的事情:您必须为每个数组元素显式调用pa[i].~a(),然后
\u aligned\u free(buf)
为此,您应该使用
\u declspec
。您的代码也会在我的计算机上生成未对齐的对象(使用VS2010),但当我更改为
\u declspec(align(8))
,指针已正确对齐


我相信,
pragma-pack
只会更改结构的大小,不会对其位置做出任何保证。

好吧,从字面上回答你的问题,我认为该标准根本没有提到任何关于#pragma-pack的内容。因此我想说,根据该标准,你的代码具有未定义的行为。

运算符new()
哪个关键字
new
在引擎盖下调用,不知道类型的对齐方式。唯一的对齐要求是
operator new()
必须为具有最大对齐要求的内置类型分配适当对齐的内存,在32位平台上通常为8(双精度的对齐要求)


话虽如此,您发布的示例按8字节边界分配了对齐的内存。

很有趣。我的第一个问题是:没有#pragma pack会发生什么?这个结构的本机对齐方式是什么。new运算符无法知道您可能已使用pragma设置了哪些选项,因此它的存在或使用感觉在这里没有任何作用。从形式上讲,它没有违反标准,因为英特尔对任何东西都不要求任何对齐(但保持适当的对齐确实有助于提高性能)。总之,它似乎不是一个理想的“功能”,但这是一个QoI问题,而不是一个标准一致性问题。

这令人难以置信。即使是我们内部自定义的
operator new
实现也尊重一致性。这难道不是您的
#pragma包(8)的结果吗
在您的main中仍然有效?@sharptooth自定义运算符new只是分配内存,编译器使用该内存为新表达式生成代码。分配的内存始终正确对齐,但编译器将对象放置在此表达式中的错误位置memory@AdrienPlisson-sizof(A)==16表示pragma pack生效于返回结果的标准grantees对齐方式。我怀疑Visual Studio是否被破坏。因此,您的假设一定不正确。我不明白您为什么认为它没有对齐…并且%zu表示大小值。项目设置中的默认打包也是8字节/zp8问题中的
结构
n包含64位成员变量,因此地址应为8字节对齐。它必须与8字节边界对齐。MS编译器向结构添加7字节填充,因此,它理解成员类型、pragma pack(以及默认对齐方式)强加的8字节要求@sharptooth:@user396672:这不是标准的要求。@Martin York:这很奇怪。为什么我们的自定义分配器确保8字节对齐…@sharptooth:不知道,但是在x86上,如果你不分配SSE类型,你就不需要8字节对齐。当然,如果你正在使用一些其他低级技术,比如CUDA,你可能需要d更多的对齐,如果你想相对容易地移植到x64,8字节对齐不是一个坏主意。这对我来说也很有效。奇怪的是,
\uuuuuu alignof(a)
即使没有
\uuuu declspec
,也给出了8。是的-如果我理解正确,pragma包只影响结构内部的对齐(例如,每个构件之间的相对偏移量)。uu declspec(align(8))同时执行这两项操作,即
printf("sizeof(A)= %d, pointer= %p", sizeof(A), pa);
#include <iostream>
#include <cstddef>
#include <cstdalign>

int main()
{
        std::cout << alignof(std::max_align_t) << "\n";
}
void* buf = _aligned_malloc (2 * sizeof (struct A), 8) ;
A* pa = new (buf) A[2];