使用展示位置新运算符时,我真的需要担心对齐吗? [英] Do I really have to worry about alignment when using placement new operator?

查看:217
本文介绍了使用展示位置新运算符时,我真的需要担心对齐吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了这个我应该什么时候担心对齐?,但我是仍然不知道是否我不必担心放置新运算符返回的不一致的指针 - 如下例所示:

 类A {
public:
long double a;
long long b;
A():a(1.3),b(1234){}
};

char buffer [64];

int main(){
//(buffer + 1)有意使用错误对齐
A * a = new(buffer + 1)A
a->〜A();
}

__ alignof(A)== 4 (buffer + 1)未与 4 对齐。但一切都很好 - 完整的例子: http://ideone.com/jBrk8



如果这取决于架构,那么我使用:linux / powerpc / g ++ 4.xx



[更新]发布此问题后,我阅读这篇文章: a href =http://virtrev.blogspot.de/2010/09/memory-alignment-theory-and-c-examples.html> http://virtrev.blogspot.de/2010/09/memory-alignment -theory-and-c-examples.html 。

解决方案


可能在我的情况下,唯一的缺点是性能损失,当您在缓冲区上调用placement new时:

  A * a = new(buf) 

您正在调用内置的 void * operator new(std :: size_t size,void * ptr)noexcept 定义:


c ++ 11



18.6.1.3布局形式[new.delete.placement]



这些函数是保留的,一个C ++程序可能不定义替换版本的函数
标准C ++库(17.6.4)。 (3.7.4)的规定不适用于
运营商新增和运营商删除的这些预留放置表格。


void * operator new std :: size_t size,void * ptr)noexcept;

返回: ptr 。 $ b备注:故意不执行任何其他操作。


<3.7>返回的指针应该被适当地对齐,因此对于 void * operator new(std :: size_t size,void * ptr)noexcept 来返回一个非对齐指针这不会让脱离钩子:


5.3.4 New [expr。注意:当分配函数返回非null值时,它必须是一个指向存储块的指针
其中空间为对象已保留。假定存储块与
和所请求的大小对应。


因此,如果将未对齐的存储传递到一个放置新表达式,你违反存储是对齐的假设,结果是UB。






确实,在上面的程序中,如果用 __ m128 b 之后)替换 long long b #include< xmmintrin.h> ),则程序将按预期进行segfault。


I read this When should I worry about alignment? but I am still do not know if I have to worry about not aligned pointer returned by placement new operator - like in this example:

class A {
public:
   long double a;
   long long b;
   A() : a(1.3), b(1234) {}
};

char buffer[64];

int main() {
   // (buffer + 1) used intentionally to have wrong alignment
   A* a = new (buffer + 1) A(); 
   a->~A();
}

__alignof(A) == 4, (buffer + 1) is not aligned to 4. But everything works fine - full example here: http://ideone.com/jBrk8

If this depends on architecture then I am using: linux/powerpc/g++ 4.x.x.

[UPDATE] Just after posting this question I read this article: http://virtrev.blogspot.de/2010/09/memory-alignment-theory-and-c-examples.html. Maybe the only drawbacks in my case would be performance penalty, I mean unaligned access cost more than aligned?

解决方案

When you call placement new on a buffer:

A *a = new (buf) A;

you are invoking the built-in void* operator new (std::size_t size, void* ptr) noexcept as defined in:

18.6.1.3 Placement forms [new.delete.placement]

These functions are reserved, a C++ program may not define functions that displace the versions in the Standard C++ library (17.6.4). The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete.

void* operator new(std::size_t size, void* ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.

The provisions of (3.7.4) include that the returned pointer should be suitably aligned, so it's fine for void* operator new (std::size_t size, void* ptr) noexcept to return a nonaligned pointer if one is passed in. This doesn't let you off the hook, though:

5.3.4 New [expr.new]

[14] Note: when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved. The block of storage is assumed to be appropriately aligned and of the requested size.

So if you pass unaligned storage to a placement-new expression you're violating the assumption that the storage is aligned, and the result is UB.


Indeed, in your program above, if you replace long long b with __m128 b (after #include <xmmintrin.h>) then the program will segfault, as expected.

这篇关于使用展示位置新运算符时,我真的需要担心对齐吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆