English 中文(简体)
配售新股
原标题:Placement new issue
  • 时间:2010-10-06 16:13:42
  •  标签:
  • c++

在此我需要C++数组类模板,它是固定大小的,基于堆栈,不需要默认构造函数答案我发布了一段代码,那就是使用带有char数组的placement new。对我来说,这是绝对正常的。但根据评论,这段代码是错误的。

有人能更详细地解释一下吗?

特别是数组可能出现的问题。我从评论中了解到,Tx[size]可能不适合charx[size*sizeof(T)]。我不相信这是真的。

编辑:

我只是越来越困惑。我知道在结构的情况下什么是对齐。是的,当你有一个结构时,属性从不同的偏移开始,你可能会想。

好的,现在我们回到数组。你是在告诉我Tx[size]的大小与charx[size*sizeof(T)]的大小相同,但我无法将char数组作为T数组访问,因为可能存在一些对齐。当数组大小相同时,如何进行对齐?

编辑2:

好吧,我终于明白了,它可能是从一个错误的地址开始的。

编辑3:

谢谢大家,你们可以停止发帖了:-)哇,这个总数让我大吃一惊。我只是从来没有意识到这是可能的。

最佳回答

Tx[size]数组将始终精确地放入size*sizeof(T)字节中,这意味着char buffer[size*sizeof(T)]

据我所知,这个答案中的问题是,您的char数组不能保证正确地对齐以存储T类型的对象。只有malloc-ed/新的-ed缓冲区可以保证正确对齐,以存储更小或相等大小的任何标准数据类型(或由标准数据类型组成的数据类型),但如果您只是显式声明char数组(作为本地对象或成员子对象),则没有这样的保证。

对齐意味着在某些平台上,可能会严格(或不那么严格)要求在例如4字节边界上分配所有int对象。例如,您可以将int对象放置在0x10000x1004地址,但不能将int0x1001位置。或者,更确切地说,您可以,但任何将此内存位置作为int类型的对象进行访问的尝试都将导致崩溃。

当您创建任意<code>char</code>数组时,编译器不知道您打算将其用于什么目的。它可以决定将该数组放置在0x1001的地址。出于上述原因,在这样一个未对齐的缓冲区中创建int数组的天真尝试将失败。

某些平台上的对齐要求非常严格,这意味着任何处理未对齐数据的尝试都会导致运行时失败。在其他一些平台上,它们不那么严格:代码可以工作,但性能会受到影响。

对正确对齐的需要有时意味着,当您想在任意的char数组中创建int阵列时,您可能必须int的开头从char数组的开头向前移动。例如,如果char数组位于0x1001,则您别无选择,只能从地址0x1004(即索引为3的char元素)开始构建就地int阵列。为了容纳移位后的int数组的尾部,char阵列必须比size*sizeof(T)的计算值大3个字节。这就是原始大小可能不够的原因。

一般来说,如果char数组没有以任何方式对齐,那么您将真正需要一个size*sizeof(T)+A-1字节的数组,以容纳必须在A字节边界对齐的T类型的对象的对齐(即可能移位)数组。

问题回答

T可以与字符不同地对齐。

此外,itaniumAbi(例如)为非pod数组指定了cookie,因此它知道在删除时要遍历多少元素(以调用析构函数)。通过new的分配如下(iirc):

size_t elementCount;
// padding to get native alignment for 1st element
T elements[elementCount];

因此对16字节对齐对象的分配是:

size_t elementCount; // 4
char padding[16 - sizeof(elementCount)];
T elements[elementCount]; // naturally aligned

在某些系统上,char可以与1对齐,因此……您可以看到错位和大小问题的适用范围。内置类型不需要调用它们的dtor,但其他所有类型都需要调用。

字符x[size*sizeof(T)]可能不接受对齐考虑在内,其中as T x[size];将。对齐(2)在处理需要16字节对齐的SSE类型时也非常重要

在某些系统上,内存访问必须“对齐”。为了简单起见,这意味着地址必须是某个整数的倍数,该整数被称为类型的“对齐要求”(参见C++标准的3.9/5)。

因此,例如,假设sizeof(int)==4

int *intarray = new int[2];        // 8 bytes
char *charptr = (char *)intarray;  // legal reinterpret_cast
charptr += 1;                      // still 7 bytes available
*((int*)charptr) = 1;              // BAD!

charptr的地址不是4的倍数,因此如果int在您的平台上具有4的对齐要求,则程序具有未定义的行为。

类似地:

char ra[8];
int *intptr = reinterpret_cast<int*>(ra);
intptr[0] = 1;  // BAD!

<code>ra</code>的地址不能保证是4的倍数。

不过,这还可以:

char ra = new char[8];
int *intptr = reinterpret_cast<int*>(ra);
intptr[0] = 1;  // NOT BAD!

因为new保证了对于任何足够小以适合分配的类型,都可以对char数组分配进行对齐(5.3.4/10)。

远离自动化,很容易理解为什么编译器可以自由地不对齐数据成员。考虑:

struct foo {
    char first[1];
    char second[8];
    char third[3];
};

如果标准保证second是4-对齐的(仍然假设int为4-对齐),则此结构的大小必须至少为16(其对齐要求至少为4)。在实际编写标准时,允许编译器为该结构提供12的大小,而不需要填充和对齐要求。

§5.3.4/10:

A new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array. For arrays of char and unsigned char, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the most stringent alignment requirement (3.9) of any object type whose size is no greater than the size of the array being created.

This allows using char arrays allocated with new for placement-construction of appropriately sized objects of other types. The pre-allocated buffer has to be allocated on the heap. Otherwise you might run into alignment problems.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?