高度注意并警惕 placement new [] 的陷阱

前几天在检一个服务器容器的时候,发现一个严重的问题,问题大概如下:

 

假设我们有这样一个类:

 

和假设如下的代码:

 

按照MSDN上面说明,我们可以认为p和pk所处的地址是相同的,仍而,
如果我们把类中的tk成员注掉,执行上面两句结果是p和pk地址相等。
但我们把类中的tk成员打开,再执行,p和pk地址却不相等。
经调试发现,中间差了4字节,里面存放的刚好就是数组的数量,即4。

 

我问了两个群的编程兄弟,他们都很热情,我很感谢,不过问题说得不是很清楚,但我更喜欢查根问底。
虽然我知道怎么解决这个BUG,让程序正常起来,但我还是硬着查清楚原因。

 

在解释原因之前我们先将结构改一下(去掉tk,增加析构函数):

 

好了,这个时候再来以有析构和没有析构函数的方法测试:
当有析构的时候p和pk地址不同,当没有析构的时候p和pk相同。

 

是什么原因造成这一现象的呢?
有没有析构又怎么会造成这一结果的呢?
类析构和std::vector< int > tk有什么联呢?
下面依次解释:

 

虽然FFntTexXX是一个类,但其成员没有一个成员有析构函数,所以编译器认为此类可以退化到结构。
(当类中有任意一个成员需要析构,如std::vector tk成员,编译器为自动为类FFntTexXX生成析构)
或许你又要问了,为什么生成析构与不生成析构和p、pk有什么关系呢?
确实是的,起初我也一直认识这个不存在任何关系的,但编过汇编发现,原因正是因为析构。

 

先看 ::new [] 函数代码(无析构):

 

再看 ::new [] 函数代码(有析构):

 

这里可能你也已经发现了,当有析构的时候new[]会要求多传入一个机器字长数据,当然目的就是为了保存数组的个数,
而没有析构的时候却不需要保存数组的个数。

 

接下来再看 constructor iterator 函数(无析构):

 

然后看 constructor iterator 函数(有析构):

 

初看这好像没有什么特别的,但细看才发现,两个数组构造器函数不一样,无析构的只有4个参数,而有析构的有5个参数。

“vector constructor iterator”和“eh vector constructor iterator”。
这时才恍然大悟,原因编译器做的事情不少。

 

总结:
因为没有析构函数的对象,在delete[]的时候,它可以直接从内存拿掉而不用调析构函数。
所以这里不用记录这个数组有多少个元素,也就不出现偏4个字节。
当有析构函数的时候,编译器为了记住有多少个对象,以便于在delete[]的时候要对其调用析构函数,
所以在数组首地址前面一个机器字长来保存数组长度,数组总尺寸增加一个机器的字长。
因此调用new[]的时候,有析构和无析构的时候,所需要的内存不一样。

 

解决方案:
使用 placement new[] 对给定地址进行数组构造的时候(placement new不存在此问题),
一定记住要多分配一个机器字长,用sizeof(int)即可得到所需字节数。
真正的数组地址应该取 placement new[] 返回的地址,而不是取 placement new(p) [] 中p的地址。

阅读更多

警惕,邮件陷阱

11-22

最近受到一封广告信,全文如下:rnrn**************************************************************************rn您好!rnrn推荐两款 WINDOWS 工具软件:rnrn 一、XX邮件地址搜寻工具 ****** 3.0 rn ===================================rnrn 软件说明:rn ****** 3.0 是一款 WINDOWS 环境下的邮件地址搜寻工具, 用它您可以把您机器的硬盘驱动器或映射驱动器的 Email 地址搜集到一起,Internet Cache 和回收站里的文件也不会漏网,如果您愿意,您甚至可以用他D4?.EXE 文件里搜寻。 rnrn ****** 3.0 支持 1000000 数量级的电子邮件搜寻,并且搜寻速度不会有随搜寻到的电子邮件数量增加而变慢的感觉。 rnrn ****** 3.0 可以指定待搜索的文件类型、目录范围,可以指定目录组合,3.0 版本支持输出格式定义,****** 输出的地址文件可以方便的被其他的邮件程序使用。以前版本的 Email 地址过滤、文件限长定?rn宓裙δ苋匀挥行А?rnrn 运行环境:win9x/NT/2000rn 软件大小:1.6Mrnrn 下载连接:http://*************************rn 主页地址:http://*************************rnrn 二、XX电子邮件群发工具 ****** 3.0 rn ===================================rnrn 软件说明:rn ****** 3.0 是一款 WINDOWS 环境下的邮件群发工具, 用它您可以一次发送成千上万封电子邮件给不同的用户。电子邮件所有的要素都可以自由设置[比如发件人、收件人等等],图形化的界面容易上手?rnrn3 rnrn 3.0 版本支持 HTML 格式的邮件, 支持附件, 支持big5繁体邮件, 支持用户验证, 可以设定邮件优先级等等;3.0 版本还增加了 SMTP 邮件服务器查找功能,免去了用户自己查找 SMTP 的麻烦[使用XX邮件地?rn7搜寻工具 ****** 3.0 可以得到大量电子邮件地址,用于 SMTP 服务器的查找]。3.0 版本支持国外的 SMTP 服务器,稳定性好,支持断线(或停止)续发! rnrn 运行环境:win9x/NT/2000rn 软件大小:1.7Mrnrn 下载连接:****************************rn 主页地址:****************************rnrn****************************************************************************rnrn看到csdn上很多朋友为了得到软件或文档而随意公布自己的电子邮件地址。很可能有意无意的成为这类邮件收集工具的猎物。油箱里的垃圾就会不知不觉的增多。rn其实csdn论坛已经提供了很好的信息交流渠道。为了保护自己的利益,建议各位尽量少公布自己的邮件地址。rn

没有更多推荐了,返回首页