流水之痕
逝者如斯
网志分类
· 所有网志
· Learning C++
· Visual Studio
· 编程点滴
· Java Web
· 电脑使用
· 网文收摘
· 读书笔记
· 影视音乐
· 体育运动
· 小日子
最新的评论
站内搜索
友情链接
· 歪酷博客
· 我的歪酷 非非共享界
· 我的Mayyang
· 陈年邻居
· 羊圈里的杨
· 葱头

订阅 RSS

0048638

歪酷博客

天下风云出我辈,一入江湖岁月催。
rocker @ 3016-10-25 22:45

    老婆的生日,希望老婆天天快乐,青春永远。在3016年的1025还是这么年轻^_^



 
rocker @ 2011-10-26 22:51

        今天发现写的一段代码,new了数组后,使用的delete而不是delete[]释放,没有内存泄漏。结合以前一些对delete和new的一些模糊了解,查阅了相关资料,整理了本文。

目录:
1、new 操作
2、delete与delete[]
3、案例分析
4、参考文献

        实验环境是Windows XP + VC6.0

1、new操作
        这里将new和new[]等不严谨的统称为new操作
        C++中提供了new操作符来进行C++类在堆上的创建。new相比较C的malloc而言,不仅分配了内存,而且对创建的C++类调用了其构造函数进行构造工作。在分配内存时,被分配的内存会有一些额外空间记录分配的大小。具体记录在哪里,找了下malloc()源代码没找着,希望知道的网友能够回复一下。先谢过了。

2、delete与delete[]
        由于new操作记录内存大小,所以delete的时候,会根据需要删除的指针的地址找到额外空间,根据其大小删除所分配的内存。这么说来,delete与delete[]在释放内存,即free这一块是一样的。存在的区别在于delete[]需要将类的析构函数作用于每一个元素。delete只是将析构作用于第一个元素。析构完成后,再释放内存。
        那为什么不将两个delete统一为delete[]呢,原因引用《深度探索C++对象模型》P259的描述,“寻找数组维度给delete运算符的效率带来极大的影响,所以才导致这样的妥协:只有在中括号出现时,编译器才寻找数组的维度,否则它便假设只有单独一个objects要被删除。”
        在平时使用中,对于new[]产生的东西,最好是使用delete[]来释放,这样可以让每个元素都得以析构,否则的话,可能会产生一些问题。比如元素类的构造中产生了内存,在析构中需要去释放内存时,使用delete便会使得从第二个开始的元素没有被析构,导致内存泄漏。

3、案例分析
        存在class CA,定义如下
         class CA
         {
         public:
               CA();
              ~CA();
         private:
              int m_iCount;
              char* m_szContent;
         };

         1)某段代码如下:
         CA* pVecA = new CA[10];
         delete pVecA;
         pVecA = NULL;
         a)如果CA的析构函数不需要释放内存不会造成内存泄漏,只是析构函数没有作用于第2-10个元素。
         b)如果CA的析构函数需要释放内存,则pVecA中2-10元素因为未执行析构,导致内存泄漏。

          2)某段代码如下:
         class CB: public CA
         {
               //内容省略
         }
         CA* pVecA = new CB[10];
         delete[] pVecA;
         pVecA = NULL;
         其中,delete[]会根据CA的大小遍历pVecA,将CA的析构函数作用于元素上,会存在两个问题。
         a)~CA()并不能满足~CB()的功能
         b)CA的大小与CB不等,导致delete[]计算元素大小时错误,CA的析构作用于不正确的内存块上。
 
         3)某段代码如下:
         CA* pVecA = new CA[10];
         pVecA++;
         delete pVecA;
         程序会异常,个人推断,是因为new[]分配的内存大小是一次分配的,其大小只记录在首元素前面的额外空间内。所以遍历一个元素之后,删除会异常。从而得到以下一个推论:
          一次new N个元素所占用的内存比new N个元素所占用的内存小,少了N-1个额外空间。

4、参考文献:
《深度探索C++对象模型》

 



 
rocker @ 2011-04-30 23:26

        这一周对于一个球迷来说,是比较充实的一周。2010-11赛季NBA季后赛第一轮尘埃落定。第二轮对阵已经出炉。今年的季后赛,见证了年轻新贵的逐步成长,见证了传统强队的落幕,见证了08年三巨头模式兴起的N巨头模式间的碰撞,而这个还将在热火与凯尔特人间继续碰撞。

西部:
        马刺VS灰熊。今天的这篇博文,正是有感于今天马刺被灰熊淘汰了。正如张卫平所说,今天的这场失利,不仅是输掉了一系列的季后赛,也是宣告了邓肯时代的结束。马刺自从抽到邓肯的状元签之后,就开始跻身强队之列,昔日邓肯与海军上校组成的双塔人人津津乐道之,过去几年的GDP组合也是值得信赖的三架马车,阿根廷妖刀蛇行步法,诡异的出手以及传球,总是让人感觉篮球除去暴力美学还有其他的艺术美感。帕克的小酒窝个人感觉与张智霖有点像,法国人朴实的华丽变向也一度让人为之炫目。至于邓肯,一直是号称史上最强大前锋来着,力压狼王。围绕他,波波维奇打造了一支在过去10年中3夺总冠军的队伍。然而岁月不会为任何人停下脚步,英雄和美人终有迟暮之年,让步于新人辈出的新晋英雄们。作为一个伪球迷,一直没有关注过灰熊。对灰熊最早的印象是在一次看体育新闻时,其中有N个行云流水的配合,以扣篮为终结,貌似都和大加索尔有关。再次的印象就和巴蒂尔和鲁迪盖伊有关了。不觉兰多夫和小加索尔已成为联盟内顶尖的内线组合了。得内线者得天下。让黑八走得更远些吧。

        湖人VS黄蜂。个人认为科比是幸运的。这里没有贬低科比的意思,科比就球技而言,也是属于超级球星一类。难得的是他在年轻时能遇到巅峰期的奥尼尔,在落寞时,拾到了加索尔。从此湖人又恢复了紫金王朝的霸相了。也许有人要说是加索尔的幸运,呵呵,幸运的事情大抵是那么回事,对的人在对的时间遇上了。蜂王保罗,CP3,精湛的球技,出色的组织才能,谦逊的品格,使得其魅力无穷,一度也曾问鼎MVP。无奈身边帮手不够。独力难行舟。好在保罗还年轻,还值得让人期待。呃。。。一言至此,貌似黄蜂除了保罗,我就还记得一个韦斯特。帮手是在太少了。

       小牛VS开拓者。小牛这个队的核心一直是诺维茨基。也曾牛过,05赛季和马刺大战7场,最终被淘汰,06赛季以常规赛第一气势汹汹的杀入季后赛,结果遭遇黑八,也使得第一轮结束后颁发的常规赛MVP给诺天王带来了讽刺与尴尬。诺维茨基、特里、霍华德、斯塔克豪斯,一众人物繁华过后,小牛最近几年也默默的消沉了。这次重新杀入第二轮,希望能够再走一把牛市。开拓者年轻,且人才辈出,有点像今天的雷霆青年军。但开拓者也是悲剧产生的地方,罗伊作为青年军领袖率先冒出来,之后来了奥登一度让我很是期待,这个传说中奥尼尔与贾巴尔的合体,然后现实是残酷的,新秀赛季因伤缺阵后,次年没打多久又伤了。今年罗伊也伤了,阿尔德里奇成为了新的闪光点,人才辈出,总得有个核心。大家都是年轻人,还真不好安排。青年军的风头也被更加年轻的雷霆夺走了。加油,开拓者。

        雷霆VS掘金。雷霆作为联盟最年轻的球队,拥有年轻的球员,一大堆年轻人宣泄着自己的激情。相比绝对核心杜兰特,近两年威斯布鲁克也光芒闪闪。雷霆也由单核晋升为双核。伊巴卡也是个弹跳狂人,貌似今年格里芬把伊巴卡和麦基的弹跳热情都给引出来了,抑或是我之前确实是没咋关注这两个弹簧男。一个拥有三个球迷耳熟能详的队员的球队总是让人感觉幸福和熟悉的。由于自己是个伪球迷,所以总感觉掘金很不着调。昔日艾弗森和小甜瓜的后场黄金双枪加上坎比,内内,马丁,不能说多么多么的强大,但是还是很让人感觉强大。结果愣是没走多远。后来小艾走了,比卢普斯来了又和安东尼一起走了。只得相信球员之间确实是需要化学反应的。就像季后赛的经验可以灭杀一个季后赛处子球队一样。

东部:
        公牛VS步行者。提到公牛,就不能不说乔丹。说来遗憾,真正开始关注NBA确实01年之后的事情。所以公牛多么牛,已成追忆。回顾98年公牛和爵士总决赛最后一场的录像,发现那时候的球队战术素养都很强。战术执行的也比较彻底。风格和现在的NBA不一样。乔丹离开公牛后,不光是公牛,整个东部也比较低迷。戈登、辛里奇、洛尔邓、托马斯一度将公牛拉进了季后赛,然后真正让人疯狂的还是这个赛季的公牛,常规赛由上个赛季的41胜提升62胜,位居东部第一。罗斯也屡屡在关键时刻神奇演出。绽放的玫瑰,让人瞩目。是偶然的走高,还是实力的体现?无论如何,今年的公牛是疯狂的。步行者队给我的印象还停留在雷吉米勒的年代。之后确实没有什么印象。貌似小奥尼尔也是出自步行者。

        热火VS76人。去年夏天。小皇帝来开了骑士,从此成为争议人物。有人说他是背叛者,是叛徒,是抱大腿的,有人说骑士让詹姆斯太失望了,离开是正确的选择。然而不管怎样,热火队的球迷幸福了。热火三巨人在赛季初期跟人无限遐想,和几个朋友聊起,都是一脸坏坏的笑,热火这个赛季怎么打啊。呵呵。不管咋样,热火还是来到了季后赛。而且新三巨头要和老三巨头火拼一把。真的是让期待啊。对于76人,小艾和大叔走后,小AI也算是尽力,这些年也还能带领球队进入季后赛。

        凯尔特人VS尼克斯。尼克斯自尤因时代之后,一直疲软。这个赛季买来了小斯,总算是各得其所。麦迪逊广场花园的主场球迷比以前幸福了,小斯也可以证明自己,离开了纳什,他依旧是那个勇不可挡的小霸王。安东尼和比卢普斯来到尼克斯后,更是让人期待,然后这第一轮季后赛确实比较运气欠缺,比卢普斯第一场没打完就伤了,第二场小斯打了一会就伤了。因为如此,所以更让人期待尼克斯下个赛季的表现。03黄金一代的前三个签都已经在东部了。凯尔特人在08年组成三巨头,那个夏天确实让我心潮澎湃。狼王总算是离开了森林狼,远走东部。经历过跌跌撞撞的季后赛,为整个球队的磨合提供了历练,最终成功夺冠后,使得联盟兴起了N巨头模式。也算是一个传奇了。虽然我有些不喜欢绿军主场的地板。

        魔术VS老鹰。在中锋缺乏的年代,魔兽横空出世,吻框男,超人,那个脸上总是带着笑容的大男孩,能感受到篮球给他带来的快乐。这几年魔兽的技术越来越全面了。而魔术这两年也火了一把,08-09赛季冷冷的就把小皇帝的骑士给灭了。特科格鲁也一度被认为是魔术的司令官,在上个赛季卡特过去后,更是让人期待新老扣篮王的表演,期待魔术的繁华。然后在季后赛被凯尔特人干了。这个赛季又转走了刘易斯和卡特,弄来了特科格鲁,阿里纳斯,理查德森,然后特科格鲁神奇不再,大将军,理查德森,传说中的化学反应又没出来。被老鹰刷落在第一轮。有些感慨,望魔兽一路走好。老鹰把魔术淘汰了,是我意料之外的,之前只是以为老鹰队的约什史密斯比较牛叉,是因为有一年他拿了扣篮王,当时的动作还是比较霸气。不想克劳福德也开始和鹰王、史密斯成为了鹰队的三架马车,让老鹰飞翔了起来。期待下一轮的精彩。

        Where amazing happens...



 
rocker @ 2010-05-11 23:06

        今天双击一个VS2005的项目,无法打开。单独启动VS2005,发现VS2005停留在启动画面,无法继续。郁闷啊。于是马上打开services.msc,启动了一些跟.NET和VS2005靠点边的服务,继续try,发现还是停留在启动画面。郁闷啊。

        网友总是万能的。在网上搜到资料。就我电脑上VS2005无法启动的过程如下:之前我安装了VMWare,用过一阵,又在360安全卫士里面把VM的服务给改为了手动启动,之后就出现了VS2005无法启动的情况。原因就在与VMWare安装的时候给VS2005添加了一个VMDebugger工具栏,VMWare的服务没有加载,这个工具栏就不能加载,导致VS2005就无法启动。这么说来,VS2005关于插件的抗击打能力还是脆了点。

        解决办法:将注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio.0\Addins\VMDebugger.Connect目录下的LoadBehavior项改为0。问题解决。

参考资料:http://topic.csdn.net/u/20080428/09/61a13b42-d385-42c3-b990-4d0b60fee061.html



 
rocker @ 2010-02-10 19:52

 
前提:在Unicode工程下,使用CString::Format(_T(“%f”, dVal);当dVal为一个很大的值,比如1.0e200,会导致异常。

         今天排查了一个故障,根据Windbg显示是CString::Format()出了问题。当时使用的代码如下:

        CString str;

        str.Format(_T(“%.2f”), dVal);

        return str;

         跟进Format的实现,找到了问题所在。在strex.cpp中可以看到,CString::Format()实现时调用了FormatV()函数。其对浮点的处理如下:

case 'f':

    va_arg(argList, DOUBLE_ARG);

    nItemLen = 128; // width isn't truncated

    // 312 == strlen("-1+(309 zeroes).")

    // 309 zeroes == max precision of a double

    nItemLen = max(nItemLen, 312+nPrecision);

    break;

...

GetBuffer(nMaxLen);

VERIFY(_vstprintf(m_pchData, lpszFormat, argListSave) <= GetAllocLength());

ReleaseBuffer();

        
        CString为浮点数分配了312+nPrecision个字节,认为可以容纳double的所有取值范围。当在Unicode情况下时,例中1.0e200实际上占据的字节大于400,而CString只分配了312+2=314个字节,导致_vstprintf函数越界,产生异常。

 
        解决方案是,不直接使用CString::Format()浮点,而是使用_stpirntf将其格式化到一个临时字符串数组中,然后赋值给CString。