指针有效性检查的函数

CrendKing 2006-04-16 12:40:41
我们都知道几乎每个 Windows 程序在加载的时候都会为它分配堆段,用于存放静态数据,栈段,用于存放动态数据。除此还有代码段,一般开始于 ImageBase 0x00400000。一般指针如果指向了一个不允许访问的地址就会 Access Violation,我想能不能有办法让程序自己从 Windows 那里获得可访问地址段,如果指针指向了非可访问地址,就跳过,避免 Exception 出现。

比如,

char* a = (char*)0x00000000;
cout << a;

肯定 Access Violation,因为 a 不属于可访问的栈段。但,

char* a = (char*)0x00300000;
cout << a;

可以打印出一些无意义的东西,虽然没有用,但不会 Exception。

当然,堆会随着程序申请的空间而不断增大,所以就要求能获得堆段的起始地址和当前结束地址。
...全文
547 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
CrendKing 2006-04-18
  • 打赏
  • 举报
回复
我知道,最简单的就是你 char* a = new char[10]; delete[] a; a 肯定是在可访问内存区(堆)申请的,但不能保证 a 指向的数据一定正确,这是 VirtualQuery 等做不到的。要想达到真正的 GC,可能还是跟踪所有的变量吧。
tutu_cloud 2006-04-18
  • 打赏
  • 举报
回复
那么指针指向了可访问但是却是错误的地址呢?如下例所示,很明显p是一个可访问的地址,因此能够通过指针有效性检查的函数。但是即使检查通过,还是会有不可预计的后果,从而造成错误很难被找出。除非你能够穷尽的检查所有的指针和数据。

class A;

void f()
{
A* p = new A();
memset( p, 0xCC, sizeof(A) ); // 模拟数据被破坏
if( IsValidAddress(p) ) // 指针有效性检查
p->DoSth();
}
ehhl 2006-04-17
  • 打赏
  • 举报
回复
可是java还支持空间压缩,就是指针移动啊
CrendKing 2006-04-17
  • 打赏
  • 举报
回复
不是打算隐藏错误,而是打算用一个 if 来判断是否有错误,如果有错,那么在 if 里面试图修正错误。相反,如果不采取这种措施,根本就没有机会修复,因为程序已经崩溃了。其实这和 try 没什么本质上的区别,只是想换一个实现的方式而已。
jiangjundu 2006-04-17
  • 打赏
  • 举报
回复
出现了错误必须给出提示并且将所有的可能不一致性的操作ROLLBACK,不能隐藏起来,跳过任何代码都将导致不可预料的后果,其损失远远比显示一个丑陋的EXCEPTION更可怕!
bobob 2006-04-17
  • 打赏
  • 举报
回复
_CrtIsValidHeapPointer
Verifies that a specified pointer is in the local heap (debug version only).

int _CrtIsValidHeapPointer( const void *userData );

可以在debug阶段检测指针是否有效,release下定义为空
adintr 2006-04-17
  • 打赏
  • 举报
回复
楼主的目的如果只是为了 "避免 Exception 出现", 你把代码放到 try/catch 里面,就可以处理这个 Exception , 不会中止程序了。
zez 2006-04-17
  • 打赏
  • 举报
回复
楼主的想法是错的!!!
是大大不可以的!!!

既然出现指针错误,那就是你的程序已经出错了..
你仅仅简单的检查一下,把这个错误抹掉,不显示出来,但实际上错误已经发生了,接下来的运行都是错误的!!!

典型隐藏错误,却不解决错误,只是 自欺欺人而已
chenhu_doc 2006-04-16
  • 打赏
  • 举报
回复
想法不错呀,
可是如果这样实现很简单的话,那么就没有谁会对指针产生畏惧了
CrendKing 2006-04-16
  • 打赏
  • 举报
回复
我觉得用 Java 或者 C# 实际上是对指针的一种妥协,毕竟,在内存操作这个极其强大的地方,Java 绝对不如 C,也限制了程序员的想象力。其实我觉得这个东西做到后面就是一个垃圾回收机制,只要我能遍历栈中所有的指针,我就能每隔一段时间检查他们,看他们指向的内存区域是否还有效。
jixingzhong 2006-04-16
  • 打赏
  • 举报
回复
呵呵,楼主的想法是好的 ~

不过 ...
这个实现就和平台相关了 ...
需要依赖系统对内存的管理和操作 ~
jixingzhong 2006-04-16
  • 打赏
  • 举报
回复
要对指针限制的话,
那就用 JAVA 好了 ....

sankt 2006-04-16
  • 打赏
  • 举报
回复
把断言宏改写成断言函数不就ok了
CrendKing 2006-04-16
  • 打赏
  • 举报
回复
嗯,可以用 VirtualQuery 检查内存空间的保护状态。VirtualProtect 似乎只能改由 VirtualAlloc 分配的页吧?
CrendKing 2006-04-16
  • 打赏
  • 举报
回复
VirtualQueryEx 应该是以页为单位的吧?在精确性上课能不能达到要求。肯定不会在每个指针访问时都调用这个函数,主要还是在比较关键的地方检查。try的话在编码上也会比较麻烦,一个块里面有多个关键指针访问的话,不添加代码将无法知道是哪个指针错误了。

我想提供一个这样的检查,至少也是一个避免程序异常退出(用户最不愿看到的)的途径,其实际意义还可以等以后慢慢发掘嘛。
tutu_cloud 2006-04-16
  • 打赏
  • 举报
回复
理论上可以使用VirtualQueryEx函数获得某个指针及从该指针地址开始的某一范围内存是否有效。但是在任何一个指针操作之前都调用这种检查的话,编码工作量和运行代价应该没有几个人能够承担的起。
Access Violation错误的出现,很多情况下是由于内部数据已经错误无法恢复造成的。如果这个时候根据检查的结果而做一些不引起Exception的保护操作,那么看上去好像程序没有问题,但实际上运行的结果将由于数据错误而导致不可确定的结果。
想避免Access Violation最好的方法就是编写好的代码,将产生Access Violation的可能行将至自己所能控制的最低程度。在自己无法控制或者难以确定的地方,加入exception handling(try或__try等)。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧