空数组 《深度探索C++对象模型》上的一处变迁

来源:互联网 发布:淘宝自定义导航条 编辑:程序博客网 时间:2024/06/03 20:56

前几天上网无意中看到一段程序,可以在VCdebug模式下面通过提取动态分配的内存前面的cookie得到具体分配了多少内存。以前我也想通过cookie来提取这个信息,但当时逐字节分析的,理不出头绪来

 

int i = *(int*)( (char*)p - 4 * sizeof( int ) );

 

当然这不具有通用性,在release模式下就不行了。

然后为它构造一个模板函数,用起来方便一点

 

template<typename T>

int getMemSize(T p)

{

 int i = *(int*)( (char*)p - 4 * sizeof( int ) );

 return i;

}

 

执行这段代码,这一直是我想干的。

 

    int *p = 0;

p = new int[0];

   cout<<getMemSize(p)<<endl;

 

本来期望输出1,因为lippman在《深度探索C++对象模型》上讲到了new的一种实现

 

 extern  void* operator new(size_t size)

{

   if(size == 0)

     size = 1;

   ……

}

 

如果传进去的size0,那么size会自动设为1。解释的原因是:每一次对new的调用都必须返回一个独一无二的指针,解决该问题的传统方法是传回一个指针,指向一个默认为1byte的内存块。

但上面的语句输出的是0p实际上分配的是零个内存单元。然后执行

cout<<(int)p<<endl;

这句,可以发现p实际上是一个指向了一个有效的内存地址。

在争论面前唯一能依赖的就只有标准了。2003的标准上这样写到:

 

When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

 

size0的时候将分配一个没有元素的数组。看来输出0是正确的。<<>>离出版到现在,已经10年了,或许这里已经发生了变迁。

但还有两个疑问,我猜测这里的p指向的地址应该是cookie的最后一个内存单元的下一内存单元,那么这样就应该可以得到一个独一无二的地址,那么当年为什么会单独分配一个lbyte的单元出来?

这种零元素数组有什么用?

另外在MFC中还使用了另外一种零元素数组。

 

class A

{

public:

     static  int a;

     static  int b[0];

     static  int c;

};

int A::a;

int A::b[];

int A::c;

 

int main()

{

     cout<<(int)(&A::a)<<endl;

     cout<<(int)(&A::b)<<endl;

     cout<<(int)(&A::c)<<endl;

}

 

这里ab的地址是相同的(如果你把b中的元素个改为一个大于0的数,就不相同了,前提是a,b,c在内存中是连续存放的,但没有理由让它们不连续存放: ) ),说明b的确是一个零元素的数组。

MFC的消息映射表中

 

static const AFX_MSGMAP_ENTRY _messageEntries[]

 

如果你没有定义消息映射,那么就为空

如果要添加消息映射项,可以像                                                    

int A::b[] = {1,2};

这样添加就行了;

原创粉丝点击