这个问题在这里已有答案:
我发现operator new []存在问题:
#include <stdlib.h>
#include <stdio.h>
class V4 { public:
float v[ 4 ];
V4() {}
void *operator new( size_t sz ) { return aligned_alloc( 16, sz ); }
void *operator new[]( size_t sz ) { printf( "sz: %zu\n", sz ); return aligned_alloc( 16, sz ); }
void operator delete( void *p, size_t sz ) { free( p ); }
//void operator delete[]( void *p, size_t sz ) { free( p ); }
};
class W4 { public:
float w[ 4 ];
W4() {}
void *operator new( size_t sz ) { return aligned_alloc( 16, sz ); }
void *operator new[]( size_t sz ) { printf( "sz: %zu\n", sz ); return aligned_alloc( 16, sz ); }
void operator delete( void *p, size_t sz ) { free( p ); }
void operator delete[]( void *p, size_t sz ) { free( p ); }
};
int main( int argc, char **argv ) {
printf( "sizeof( V4 ): %zu\n", sizeof( V4 ));
V4 *p = new V4[ 1 ];
printf( "p: %p\n", p );
printf( "sizeof( W4 ): %zu\n", sizeof( W4 ));
W4 *q = new W4[ 1 ];
printf( "q: %p\n", q );
exit(0);
}
生产:
$ g++ -Wall main.cpp && ./a.out
sizeof( V4 ): 16
sz: 16
p: 0x55be98a10030
sizeof( W4 ): 16
sz: 24
q: 0x55be98a10058
当我包含operator delete []时,为什么alloc大小会增加到24?这搞砸了我对齐的malloc。
$ g++ --version
g++ (Debian 7.2.0-18) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
从查看其他问题,似乎可以使用额外的8个字节来存储数组大小。即使这是预期的行为,为什么它由operator delete []触发,分配内存对齐数组的正确程序是什么?
编辑谢谢,链接的问题似乎是相关的。不过,我仍然认为问题需要一个答案。在我看来,应该可以更改示例代码以生成内存对齐的数组,而无需求助于std :: vector。我目前的想法是,有必要分配一个16字节对齐的更大字节块,并返回指针,使得最初的8个字节使块的其余部分在16字节边界上对齐。然后delete []操作符必须在调用free()之前执行反向操作。这非常恶心,但我认为需要同时满足调用代码(C运行时?)(需要8字节进行大小存储) - 以及用于获得16字节对齐的Vector4s的用例。
编辑链接的答案肯定是相关的,但它没有解决确保正确的内存对齐的问题。
编辑看起来这段代码会做我想要的,但我不喜欢delete []中的幻数8:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
class W16 { public:
float w[ 16 ];
W16() {}
void *operator new( size_t sz ) { return aligned_alloc( 16, sz ); }
void *operator new[]( size_t sz ) {
size_t r = sz % sizeof( W16 );
size_t ofs = sizeof( W16 ) - r;
size_t _sz = sz + ofs;
void *p1 = aligned_alloc( sizeof( W16 ), _sz );
void *p2 = ((uint8_t *) p1) + ofs;
printf( "sizeof( W16 ): %zx, sz: %zx, r: %zx, ofs: %zx, _sz: %zx\np1: %p\np2: %p\n\n", sizeof( W16 ), sz, r, ofs, _sz, p1, p2 );
return p2;
}
void operator delete( void *p, size_t sz ) { free( p ); }
void operator delete[]( void *p, size_t sz ) {
void *p1 = ((int8_t*) p) + 8 - sizeof( W16 );
printf( "\np2: %p\np1: %p", p, p1 );
free( p1 );
}
};
int main( int argc, char **argv ) {
printf( "sizeof( W16 ): %zx\n", sizeof( W16 ));
W16 *q = new W16[ 16 ];
printf( "&q[0]: %p\n", &q[0] );
delete[] q;
}
输出:
$ g++ -Wall main.cpp && ./a.out
sizeof( W16 ): 40
sizeof( W16 ): 40, sz: 408, r: 8, ofs: 38, _sz: 440
p1: 0x559876c68080
p2: 0x559876c680b8
&q[0]: 0x559876c680c0
p2: 0x559876c680b8
p1: 0x559876c68080
编辑标题已从评论中的反馈更改。我不认为这是链接答案的“重复”,但我不知道我是否可以删除它。
看起来这对我有用:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
inline void *array_alloc( size_t sz_obj, size_t sz_req ) {
size_t r = sz_req % sz_obj;
size_t ofs = sz_obj - r;
size_t sz = sz_req + ofs;
void *p1 = aligned_alloc( sz_obj, sz );
void *p2 = (void*) (((uintptr_t ) p1) + ofs);
//printf( "sz_obj: %zx, sz_req: %zx, r: %zx, ofs: %zx, sz: %zx\np1: %p\np2: %p\n\n", sz_obj, sz_req, r, ofs, sz, p1, p2 );
return p2;
}
inline void array_free( size_t sz_obj, void *p2 ) {
void *p1 = (void*) (((uint8_t*)p2) - (((uintptr_t)p2) % sz_obj));
//printf( "\np2: %p\np1: %p", p2, p1 );
free( p1 );
}
class W16 { public:
float w[ 16 ];
W16() {}
void *operator new( size_t sz ) { return aligned_alloc( 16, sz ); }
void *operator new[]( size_t sz ) { return array_alloc( sizeof( W16 ), sz ); }
void operator delete( void *p, size_t sz ) { free( p ); }
void operator delete[]( void *p, size_t sz ) { array_free( sizeof( W16 ), p ); }
};
int main( int argc, char **argv ) {
//printf( "sizeof( W16 ): %zx\n", sizeof( W16 ));
W16 *q = new W16[ 16 ];
printf( "&q[0]: %p\n", &q[0] );
delete[] q;
}
编辑感谢n.m.,这段代码没有神奇的数字。