一秋草木

Nothing Is Impossiable!
posts - 11, comments - 10, trackbacks - 0, articles - 2
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

对象的动态分配(Dynamically Allocated Object)

Posted on 2006-08-05 12:55 一秋草木 阅读(3415) 评论(4)  编辑 收藏 引用 所属分类: C++

1 、对象的分类

        全局对象( Global Object )                     Controlled by System

        局部对象( Local Object )                      Controlled by System

        动态生成对象( Dynamically Allocated Object           controlled by programmer

 

2 、动态对象的生与死

        创建: new

        销毁: delete

 

3 、动态对象的创建的地址

         内存池( memory pool )中的一块程序自由存储区域( free store area ),实际上就是通常所说的堆( Heap

 

4 、动态对象的存在形式

        简单对象( single object

        对象数组( array object

        The placement new express

 

5 、动态对象的使用

        动态对象的操纵

动态对象没有名称,而是返回分配对象的指针地址,所有操作都是通过指针间接完成

        动态对象的初始化

动态对象分配的内存区域是没有初始化过的,里面存在的是随机数据

 

6 、动态对象及指针的生命周期

        动态对象

持续时间为 new ç è delete

        指针

根据其自身类型决定(全局 / 局部)

 

7 delete 的使用

1

         int  *pi=new int;

         if(pi!=0){

           delete pi;

}      

该段程序运行起来是没有问题的,但是却存在画蛇添足的一笔: if(pi!=0)

         原因是, delete 会自动完成这个测试,如果显式地测试,将会多执行一次测试。所以说完全没有必要。

        

         2

                   pointer=0;                    // 不指向任何对象

                   delete pointer;              // 没有必要

        

         总结:

也许会有人觉得两个例子似乎有点矛盾,其实上述例程的意思是:

        当我们不知道一个对象内存是否已经释放的时候,直接 delete 即可,是没有任何问题的;额外的判断完全没有必要,反而会增加系统的工作量。

        当我们明确地知道对象指针 ==NULL 时,表明已经释了对象。这时就可以少写一行代码了。当然如果有人想看看计算机又没有不良反应,另当别论。

同时也证明了①,删除一个 NULL 对象是没有任何问题的

 

8 、动态内存分配常见错误

        内存泄露

我想这个问题对 C++ 程序员来说,是非常熟悉的。

u        根源是:?

简短的回答: new delete 没有配对使用

明白了吗?还不明白? next

                  只给对象分配了内存,但是直到关闭程序的时候,都还没有向对象要回那块内存。

u        怎样发现?

Ø         Vc IDE 中, debug 状态,程序结束时 output 窗口的 Detect Memory leak

Ø         使用工具软件,如: BoundCheck

 

u        如何避免?

呵呵,知道了根源就应该知道该咋办了。。。

        

        / 写已经删除的对象(内存)

当对象 delete 以后,对象内存被系统回收,其指针就指向到一块非法的内存。如果再对该对象指向内存操作就会导致不可预知的错误。因此,通常的做法是 delete 之后,立即赋 NULL

 

        内存 corruptted

很熟悉,是吧?不要着急,请听我慢慢道来。。。

         未命名.bmp

根源:

u        ptrA ptrB 都指向同一块内存

u        通过 ptrA 释放内存 Mem0 Mem0 分配给其它对象 ptrC

u        ptrB 释放内存 , Mem0 存储的 ptrC 指向的新对象就被破坏掉了。

u        再次对 ptrC 操作就会出错

 

        对象类型错误

例:

CDialog  dlg=new CDialog

delete dlg

                  你能发现什么不对吗?

                   提示一下, debug 运行会发现 mem leak

                   知道了吧, what

                  就是 delete dlg                   

5.1 中说过, new 返回的是指针。所以应该将 dlg 声明为 CDialog* 类型。

 

这个主题的内容就讲完了,还有一些相关内容在接下来的文章中见:

u        The placement new express

u        内存冲突

u        内存 corruptted 解决办法

Feedback

# re: 对象的动态分配(Dynamically Allocated Object)  回复  更多评论   

2006-08-06 09:46 by thanksgiving
最近我遇到了一个BUG,一直找不出原因,看到你这篇文章,我想问问你是否遇到过类似的问题.
我前几天买了台新电脑,P4 64bit的CPU,我的旧电脑是AMD 64bit的,都是32位的XP系统,我的程序在我的旧电脑上运行了了20多天(15-30个进程,每天运行20个小时),从来没有发生过内存异常.但我的程序在新电脑上频繁发生异常,运行3个进程平均二小时就会发生一次,经过调试发现异常总是出现在内存分配和释放里:
1:局部string对象的自动释放出错(STL的string);
2;new出错,而且new的字节也很小,才200字节左右;
3:delete出错,被删除的内存块调试发现也是正常的,并不是无效内存块;

开始我以为是因为多个线程同时申请堆内存,导致出现争夺的情况,于是我给每一个new和string构造的地方都加了EnterCriticalSection(&cs);LeaveCriticalSection(&cs);,结果还是频繁出现异常.

这BUG真的很古怪,而且我在我同学的电脑上运行了4天(60个进程,20小时每天),一个异常都没出现

# re: 对象的动态分配(Dynamically Allocated Object)  回复  更多评论   

2006-08-06 14:00 by 一秋草木
@thanksgiving
1、出错的提示是什么?能否更进一步描述一下?
2、建议使用boundcheck,或在debug状态看看,确认出问题的地方的对象是否在其它的地方有关联。这是最原始的办法了。
3、另外内存块有数据不一定是正常的,有可能分配给了其它对象;

# re: 对象的动态分配(Dynamically Allocated Object)  回复  更多评论   

2006-08-08 16:25 by thanksgiving
都是
0x7c931ec3 处未处理的异常: 0xC0000005: 写入位置 0x018990ba 时发生访问冲突 。
0x7c931f52 处未处理的异常: 0xC0000005: 读取位置 0x000c01e3 时发生访问冲突 .这样的异常
观察调用堆栈发现问题都在new和delete函数里,发生的错误都在ntdll.dll

还有就是错误报告也很有意思,明明是intel的CPU,可它的提示是
错误报告:CPU AMD Feature Code: 00C3E824......
我的代码应该没问题,要不然怎么在我的旧电脑和我同学的电脑上没发生过内存异常

# re: 对象的动态分配(Dynamically Allocated Object)  回复  更多评论   

2006-08-10 16:44 by 一秋草木
呵呵,这种情况我也不确定了。
建议你到微软的知识库上去看看。里面有很多异常的介绍。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理