请战友们帮忙解释下 对未赋值的指针调用 为什么会报异常, ( 积分: 50 )

  • 主题发起人 主题发起人 redcoffee
  • 开始时间 开始时间
这个是一个明显的野指针,程序中应该尽量避免在没有对指针进行初始化的时候就直接访问
 
下面这两个问题虽然形式不一样,但是本质是一样的,请楼主参考:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1294954
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2652090
 
我看看一个进程是如何分配使用内存,因为一个WIN32下的程序可用的内存是一个FLAT模式的4G空间,
 
了解了,把成员变量变为基本类型就可以,integer
 
我觉得要了解 是有“存在不能访问的地址”访问了“就会报错”不就行了。
 
其实,你的问题很好解答。
windows为每个进程准备了4G虚拟内存是不假,但是,这4G内存是有属性的。
要想使用内存,必须先告诉操作系统:这块内存给我留着,我要用,于是乎,操作系统就把你指定大小及位置的内存给你保留下来了,这时候,仅仅是保留出来了,就好像圈地运动,地是圈起来了,但是里面杂草太多,你想在这里面种庄稼?那对不起,请先初始化,也就是需要告诉操作系统,你对这块保留的内存要做什么操作,如果你不做这个告知操作就在这块内存中瞎搞,操作系统就会给你个异常:what are you doing? How do I do??? (呵呵)

如果你想用这块内存,那么你还要告诉操作系统:这块内存我要放程序代码,我需要:执行、只读 就可以了,于是,操作系统就把这块内存标示成 只读、可执行 任何想向这块内存写入的操作,操作系统就会给你个异常:嘿,玩儿呢!!,这里是只读区!!(哈哈)
你当然也可以告诉操作系统,这块内存是可读写的,那么,你向这块内存中读数据或者写数据都没有问题,但是,却不能用来执行。
这里面,有一些内存比较特殊,是被操作系统预留的,比如地址是 0 的内存。这些地址是特殊用途的,用户不能重新分配它没(也就是说,那$G内存,至少有1G被操作系统强占了,哈哈,不讲理是吧,微软就这脾气,呵呵)
好了,再加入点说明,在这4G内存中,有堆和栈,栈是预先分配好的一块可读写的内存,原则上你只能访问栈顶元素,不过这仅仅是原则上(原则就是用来被某些人违反的,哈哈),你要是玩阴的,完全可以访问到栈中任何地方的数据,只要你知道地址,呵呵。
好了,现在再说你的问题:
你的那个指针如果是局部变量,那会包含一个随机数(全局变量会被初始化为0),当你把这个随机数当指针使用,那么会发生什么呢?
会有不幸的事情发生!轻则异常,重则进程被结束或者发生不可预测的事情!
例如:你的这个随机指针指到了栈上,那么,你的读写操作都不会有什么异常,但是,你读完了,也写完了,也不出异常,你是爽了,操作系统可没你那么幸运,因为栈中可能会保存着程序的某些跳转地址(比如,函数在调用之前会把当前地址压入堆栈,函数返回时要依靠这个地址继续执行),如果你不幸修改了这个跳转地址,那么你就等着莫名奇妙的错误吧。
如果你的指针指在了未配的区域,那操作系统会直接给你个异常。
你声明的结构中,包含了String类型的数据,这本身又是一个指针类型的数据,而且还是比较特殊的指针数据。你访问那个P指针不出错就够幸运的了,还要访问下一层的指针,呵呵要想p.a也不出错,那需要:p包含的随机数指定的地址可读写(至少要可读),然后这个可读写的地址的头4包含的值作为指针,其所指向的地址也需要可读写,哈哈,你想想,你需要多幸运才能都不出错啊!这就好比你向天上扔了块石头,结果正好把上帝他小姨子给打了,还正好被上帝看到了,哈哈!至于你说的那个结构中包含了整数就不出错,那完全是幸运,只不过这个幸运的概率大了点,就好比你向天空扔个石头,然后把自己给打了。呵呵。
好了,写这么多了,估计你能知道那个异常是咋来的了吧。
 
楼上的写的不错:)
 
文章不好. 象看小说一样
对你的景仰之情有如滔滔江水
 
说白了就一句话:
如果你访问了未预留或者预留了但是未提交的内存,操作系统会触发一个异常,进而这个异常被Delphi反馈给了用户
 
楼上说的不错,真的……
而且对付这种异常,我以前用过一个方法,就是写一个异常处理,把所有这类越界都包含进去,然后把传过来的那个指针通过随便一个分配内存的API实力化就ok了。
另一种方法,申请一个无比大的数组,然后操作那个数组的头一个元素的指针一般就不会有问题了。
再另一种方法,基本和上面一样,只是不要用数组,而用tlist对象,只是知道tlist的人不多。
 
没有想到还有这么多好心的高手来帮忙,谢谢啦。我仔细看看先
 
暂且称呼放飞前辈吧,谢谢你。你说的很耐看,内存可读、可写可以理解,内存是否可以执行是怎么回事。我查查
 
未初始化的指针指向的未必都是随机数.
现代操作系统都是分页式管理内存.如果未初始化的指针所指是没有映射过的内存.访问肯定会出错.
如果你是实模式下的DOS程序,由于没有采用分页式管理,不会出错的.保证内存足够大的情况下.
 
这两天看看相关书籍,基本上理解了。
再次感谢大家鼎力相助
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
694
import
I
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部