注册 登录
编程论坛 C++教室

系统是如何区分已分配内存,和未分配内存的?

go_hao 发布于 2009-11-06 16:48, 1327 次点击
系统是如何区分已分配内存,和未分配内存的?
比如用new分配出内存,用指针 p 指向它,然后再次delete这块内存,
我发现,

*p取值的话,前后的值是不同的。
我不理解,因为delete是释放那块内存,但是并没有改写这块内存呀,为何取值会不同呢?

当然,你会说,释放的空间是不能用的,这个我也知道,我就是想明白一下,释放了的空间,在内存块不被改写的情况下,为何用同一个物理指针取它的值的话,值却真的变了,这是为什么呢?

#include <iostream>
using namespace std;

int main()
{
    int *a=new int;
    *a=90;
    cout < < "值为:" < < *a < < endl;
    cout < < "地址为:" < < a < < endl;
    delete a;
    cout < < "值为:" < < (int)*a < < endl;  //此时值已经变了(release版本照样变)
    cout < < "地址为:"  < < a < < endl;
   
    cin.get();
    return 0;
}
6 回复
#2
最左边那个2009-11-06 18:15
首先看了很久,还是不太确定你在问什么!不过还是能解释一点!
int *a=new int   开辟了一个int的空间,它的地址是a
    cout < < "值为:" < < *a < < endl;
    cout < < "地址为:" < < a < < endl;
那么上面两句毫无疑问!
delete a以后,就是把a指向的空间释放了,里面已经没什么内容了!
但是空间的地址还是在的!
所以cout < < "值为:" < < (int)*a < < endl,居然空间里没东西,那么系统就会胡乱读出一些东西出来!
cout < < "地址为:"  < < a < < endl,这个没变,是因为delete a,释放的是空间,不是地址,而单纯对地址操作还是可以的!

个人理解,如果有什么不对的地方,还请指教!
#3
lintaoyn2009-11-06 19:45
销毁这个词比释放更贴切(一本好像叫《C++陷阱》的书里说的)delete是销毁了所对应new申请空间里的内容。
我用VC++写了几行代码看了下,被改的挺有规律的。110111011101110...
#4
go_hao2009-11-06 22:32
以下是引用最左边那个在2009-11-6 18:15:01的发言:

首先看了很久,还是不太确定你在问什么!不过还是能解释一点!
int *a=new int   开辟了一个int的空间,它的地址是a
    cout < < "值为:" < < *a < < endl;
    cout < < "地址为:" < < a < < endl;
那么上面两句 ...
谢谢,不过我问的真不是这个,我是问,我释放的那块内存,我没有重写的,为何内容会变。
因为delete后,我再次访问那个物理地址存放有值,确实变了。
#5
最左边那个2009-11-07 11:55
回复 4楼 go_hao
delete a以后,就是把a指向的空间释放了,里面已经没什么内容了!
但是空间的地址还是在的!
所以cout < < "值为:" < < (int)*a < < endl,居然空间里没东西,那么系统就会胡乱读出一些东西出来!

这就是解释啊
#6
东海一鱼2009-11-07 17:01
在C、C++库级,都提供了自己的‘堆’管理函数。你请求分配的动态内存在‘堆’上被分配后,管理函数会在内部表示该块内存被使用。这样你没有释放,就不会被再次分配。
一旦你释放了这块内存,堆内存管理函数会视当前‘堆’的使用情况将其回收(取消内部表示该块内存被使用)。如果你当前使用的是Debug版本的库,在该块内存会被填写固定标示值,以方便调试器的跟踪。如果是release版本,其值会根据‘堆’管理器的回收算法不同而不同。

#7
go_hao2009-11-07 22:11
以下是引用东海一鱼在2009-11-7 17:01:13的发言:

在C、C++库级,都提供了自己的‘堆’管理函数。你请求分配的动态内存在‘堆’上被分配后,管理函数会在内部表示该块内存被使用。这样你没有释放,就不会被再次分配。
一旦你释放了这块内存,堆内存管理函数会视当前‘ ...
看来您真是高手呀,虽然我还是不明白,但是我已经知道,这个太深了,我现在还没有能力去了解其机理。
1