C ++的新操作有没有保证地址返回的一致性?

大多数有经验的程序员知道数据alignment对于程序的性能很重要。 我看到一些程序员编写程序,分配比他们需要更大的缓冲区大小,并使用alignment的指针作为开始。 我想知道是否应该在我的程序中这样做,我不知道C ++的新操作返回的地址是否alignment。 于是我写了一个小程序来testing

for(size_t i = 0; i < 100; ++i) { char *p = new char[123]; if(reinterpret_cast<size_t>(p) % 4) { cout << "*"; system("pause"); } cout << reinterpret_cast<void *>(p) << endl; } for(size_t i = 0; i < 100; ++i) { short *p = new short[123]; if(reinterpret_cast<size_t>(p) % 4) { cout << "*"; system("pause"); } cout << reinterpret_cast<void *>(p) << endl; } for(size_t i = 0; i < 100; ++i) { float *p = new float[123]; if(reinterpret_cast<size_t>(p) % 4) { cout << "*"; system("pause"); } cout << reinterpret_cast<void *>(p) << endl; } system("pause"); 

我正在使用的编译器是Visual C ++ Express 2008.似乎所有返回的新操作的地址都是alignment的。 但我不确定。 所以我的问题是:有没有保证? 如果他们有保证,我不必自己来,如果没有,我必须。

标准(3.7.3.1/2)alignment有如下保证:

返回的指针应适当alignment,以便可将其转换为任何完整对象types的指针,然后用于访问分配的存储中的对象或数组(直到通过调用相应的释放函数明确释放存储器) 。

编辑 :感谢timday突出gcc / glibc中保证不保留的错误。

编辑2 :本的评论突出了一个intersting边缘情况。 分配例程的要求仅适用于标准提供的要求。 如果应用程序有自己的版本,那么结果就没有这样的保证。

这是一个迟到的答案,但只是为了澄清在Linux上的情况 – 在64位系统内存总是16字节alignment:

http://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html

malloc或realloc在GNU系统中返回的块的地址总是8的倍数(或64位系统上的16)。

new运算符在内部调用malloc (请参阅./gcc/libstdc++-v3/libsupc++/new_op.cc ),所以这也适用于new

作为glibc一部分的malloc的实现基本上分别在x86-32和x86-64系统MALLOC_ALIGNMENT定义为2*sizeof(size_t)size_t是32bit = 4byte和64bit = 8byte。

 $ cat ./glibc-2.14/malloc/malloc.c: ... #ifndef INTERNAL_SIZE_T #define INTERNAL_SIZE_T size_t #endif ... #define SIZE_SZ (sizeof(INTERNAL_SIZE_T)) ... #ifndef MALLOC_ALIGNMENT #define MALLOC_ALIGNMENT (2 * SIZE_SZ) #endif 

顺便说一句, MS文档提到了一些关于malloc / new返回地址的16字节alignment方式,但是从实验来看并不是这样。 我碰巧需要一个项目的16字节alignment方式(用加速指令集来加速内存拷贝),最后我诉诸写我自己的分配器…

该平台的new / new []操作符将返回具有足够alignment的指针,以便使用基本数据types(double,float等)执行良好的操作。 至less任何明智的C ++编译器+运行时应该这样做。

如果你有像SSE那样的特殊的alignment要求,那么使用特殊的aligned_malloc函数或者自己动手可能是个好主意。

我在一个系统上工作,他们使用alignment来释放奇怪的位,供自己使用!

他们用奇数位来实现虚拟内存系统。

当一个指针设置了奇数位时,它们用来表示它指向(从奇数位减去)信息从数据库获取数据而不是数据本身。

我认为这是一个特别讨厌的编码,这是非常聪明的自己的好!

托尼