これはうまくコンパイルされます:
#include <cstddef>
#include <stdlib.h>
typedef unsigned int uint;
class C{ // just here to be faithful to the original code
int y;
};
class A{
public:
typedef A this_type;
void* operator new(size_t enfacia_size, uint count){
size_t total_size
= enfacia_size
+ sizeof(int) * count; // the 'tail'
;
this_type *new_pt = (this_type *)malloc(total_size);
new_pt->count = count;
return new_pt;
};
uint count;
};
class B : public C, public A{
public:
int i;
};
int main(){
B *b_pt = new(5) B;
uint j=0;
j++;
};
gdbに表示される「問題」は次のとおりです。
(gdb) b main
Breakpoint 1 at 0x80484e1: file try_offsets.ex.cc, line 32.
(gdb) r
Starting program try_offsets
Breakpoint 1, main () at try_offsets.cc:32
(gdb) n
(gdb) p &(b_pt->count)
$1 = (uint *) 0x804a00c
(gdb) x/10 b_pt
0x804a008: 5 0 0 0
0x804a018: 0 0 0 0
0x804a028: 0 135129
(gdb) p b_pt
$2 = (B *) 0x804a008
(gdb)
count は 0x804a00c にありますが、count に代入すると 0x804a008 に書き込まれることに注意してください。このタイプがテンプレートを介して子に設定されているRobによって指摘されたバリエーションがあります:
#include <cstddef>
#include <stdlib.h>
typedef unsigned int uint;
class C{ // just here to be faithful to the original code
int y;
};
template<typename this_type>
class A{
public:
void* operator new(size_t enfacia_size, uint count){
size_t total_size
= enfacia_size
+ sizeof(int) * count; // the 'tail'
;
this_type *new_pt = (this_type *)malloc(total_size);
new_pt->count = count;
return new_pt;
};
uint count;
};
class B : public C, public A<B>{
public:
int i;
};
int main(){
B *b_pt = new(5) B;
uint j=0;
j++;
};
正しい動作が得られます。
(gdb) b main
Breakpoint 1 at 0x80484e1: file try_offsets.ex.cc, line 32.
(gdb) r
Starting program
Breakpoint 1, main () at try_offsets.cc:32
(gdb) n
(gdb) p &(b_pt->count)
$1 = (uint *) 0x804a00c
(gdb) x/10 b_pt
0x804a008: 0 5 0 0
0x804a018: 0 0 0 0
0x804a028: 0 135129
(gdb)
ただし、興味深いことに、このソリューションでは、this_type が「A」に設定されているとコンパイルされません。
class B : public C, public A<A>{
public:
int i;
};
与えます:
try_offsets.cc:26:31: error: type/value mismatch at argument 1 in template parameter list for ‘template<class this_type> class A’
try_offsets.cc:26:31: error: expected a type, got ‘A’
私が落ち着いた解決策:
#include <cstddef>
#include <stdlib.h>
typedef unsigned int uint;
class C{ // just here to be faithful to the original code
int y;
};
class A{
public:
typedef A this_type;
A(uint count):count(count){;}
void* operator new(size_t enfacia_size, uint count){
size_t total_size
= enfacia_size
+ sizeof(int) * count; // the 'tail'
;
this_type *new_pt = (this_type *)malloc(total_size);
return new_pt;
};
uint count;
};
class B : public C, public A{
public:
B(uint count):A(count){;}
int i;
};
int main(){
B *b_pt = new(5) B(5);
uint j=0;
j++;
};
これは古い慣習を破りますが。アロケーターが割り当てポイントのすぐ上に割り当ての長さを書き込むのは正常です。つまり、たとえば、delete/free がヒープ上のブロックの長さをどのように認識しているかです。また、演算子 delete は引数を取ることができないため、これが情報を取得する方法です。