关于一般性保护错误的原因和解决办法

 一 什么是一般性保护错误(GP)?
      一般性保护错误(general protect简称GP),通常只是WINDOWS下的一个术语,我们现在也常把它引用到UNIX下指程序的崩溃。
      本文主要探讨WINDOWS下面程序GP的原因,预防和解决办法。
二  GP的原因
       WIN32操作系统在发现某应用程序企图访问不属于自己的非法的内存区域时,将触发一般性保护错误,立刻终止该应用程序,防止该程序破坏其他程序的内存数据,对其他程序造成不良影响。
       如果该机器上装Dr Washington软件,该软件将捕捉该错误,并出错时的应用程序内存地址情况抓下来,但实际上要分析的话,恐怕需要专门的工具。

如果没有装Dr软件,通常会弹出一个对话框,类似提示为该应用程序非法的访问了0XEFEDCD的错误出来。

如果应用程序为Debug版本,这时候弹出的对话框可能会友善一点点,有时会弹出一个Assert对话框,要你调试还是放弃来着。

以下具体分析导致GP的种种原因:

1 编译器的BUG或编译开关设置不当。

已经有文档和实践证明,VC6.0编译器在缺少补丁的情况,使用最大速度优化将导致程序在某种特殊情况下GP。

编译开关建议一律采用单字节对齐,否则接口程序越多,不一致的对齐方式最后有可能导致GP。

2 库文件或其他配置支撑文件缺少,或者不匹配。

比如原来正常工作的应用程序和配套的DLL,将其中一个DLL用另一个同名但版本不同的DLL替换将导致GP。这是很容易理解的,不同DLL的函数内存映象是不同,应用程序企图通过一个非法的地址访问函数自然会GP。

另外一个常见的例子时winsock的支持版本不一致。使用了winsock的高级特性,但支持库却跟不上。

还有一个例子也很有代表性,几个软件使用一个共用的库文件,其中一个软件升级后,偷偷将该库文件给替换了,导致其他软件不能正常使用。

3 不安全的API函数

分为几类说明

3.1 字符串函数

strlen WIN32下面传入不能为空

sprintf 前面的%和后面的参数不匹配。

建议使用snprintf而不是sprintf,因为前者判断缓冲溢出,后者不判断。

Strcat,在后面叠加时,一定要判断缓冲大小。

Strcpy

3.2 内存函数

memset,memcpy等,一定要判断内存地址有效性,以及大小等。

3.3 时间函数

localtime 不能传入-1

3.4 其他入参有特殊要求的函数,使用时请仔细查看MSDN。

4 数组访问越界,包括上下界。

5 访问到malloc所分配的内存区域后面的内存。

6 用malloc分配了内存,却不检验其合法性。

比如 用子函数分配堆上内存,在子函数中虽然有出错判断,但调用函数却根本没有考虑。
虽然从一般情况下考虑,WINDOWS采用虚拟内存方式,一般不会malloc失败,但是在系统非常繁忙且硬盘空间狭小的情况,一次性分配巨量堆上内存,仍然会可能会malloc失败

7 已经释放malloc分配的内存,却没有把malloc返回的指针置为NULL,另一个地方企图使用该指针指向的内存数据。

8企图重复释放malloc分配的内存。

9 两个函数使用一个全局数据结构,结构中有指针成员,该指针指向第一个函数在在堆栈上分配的一块内存,第二个函数企图通过该指针成员访问那块内存。

10 第一个函数返回一个堆栈上的内存地址为返回值,第二个函数企图使用第一个函数的返回值来获取该内存上的数据。堆栈上分配的内存地址,在函数退出时,该空间内的数据随时可能被其他函数覆盖,所以为不可用数据。

11 数值被0除。(此属于溢出错误,不属于访问内存失败,放在这只是为了提醒)

12 企图改变存储在静态存储区的常量字符串字面值。

13 企图对右值赋值。

14 企图使用一个空指针,经常出现在函数中使用入口指针时不进行判断。

15 消息接口定义不一致,经常出现在各接口程序的头文件定义不一致,导致非法的消息操作。比如 字节序转换时由于对方送来的消息比预期的小,就会访问到后面的内存区域,导致GP。

17 病毒或不同格式文件系统反复拷贝程序导致文件被破坏,注意检查文件大小和时间是否变化。

16 操作系统的bug,通常操作系统和复杂软件比如ORALCE数据库等的兼容性问题,这种问题,只有到微软的站点和相关公司的站点多下点补丁吃吧。

三解决办法
1 预防性校验 包括指针有效性判断,函数入参判断。

2 利用断言assert发现问题。

3 调试时分为两种现象:比如API,数组越界这种问题单步跟踪很快可以发现问题,象第五种有时表现出来非常奇怪,一会在这函数,一会那函数出现,利用函数体简化的方法,可排除干扰项。

注意查看堆栈记录,函数调用顺序。

4 利用调试日志。

5 利用程序崩溃内存映像分析。

6 采用环境比较法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果 `openProcess` 返回值为空,可能是由于以下几种原因之一: 1. 您输入的进程名不正确。请确保您输入的是正确的进程名。 2. 该进程并不存在。请确保该进程已经启动,并且您有权限打开它。 3. 您没有权限打开该进程。请确保您具有打开该进程的权限。 如果您无法解决问题,建议您尝试调试程序,以查看具体的错误信息,并根据错误信息进行修改。 ### 回答2: 当使用OpenProcess函数时,如果返回值为空,可能是由于以下几种原因: 1. 参数错误:请确保传递给OpenProcess函数的参数正确无误。参数一般包括进程标识符(PID)和访问权限等。请检查PID是否存在,以及访问权限是否正确。 2. 缺乏适当的权限:某些系统进程或特权进程受到保护,需要管理员权限才能访问。请确保以管理员身份运行程序或为程序添加适当的特权。 3. 进程不存在:如果传递的PID表示的进程不存在或已经退出,OpenProcess函数将返回空。请先确认目标进程是否正确运行。 4. 32位和64位进程不匹配:在64位系统上,如果以32位应用程序调用OpenProcess来打开64位进程,则返回值可能为空。请确保应用程序与目标进程的位数匹配。 5. 其他错误:如果以上方法都无效,请考虑使用其他调试工具或在代码中添加错误处理机制,以便查找和解决问题。 总之,要解决OpenProcess返回值为空的问题,需要仔细检查传递的参数、权限、进程状态和应用程序位数等因素,并采取相应的处理措施。 ### 回答3: 当OpenProcess函数返回空值时,表示打开进程失败。产生这种情况可能有以下几种原因和对应解决方法: 1. 无法找到指定的进程ID或句柄:确保传入OpenProcess函数的进程ID或句柄是有效的。可以在调用OpenProcess函数之前使用合适的方法获取进程ID或句柄。 2. 缺少足够的权限:有些进程可能需要更高的权限才能进行打开操作。可以尝试以管理员身份运行程序或者提升权限,以确保具备足够的权限来打开指定的进程。 3. 进程不存在或已经结束:当进程不存在或已经结束时,OpenProcess函数将无法成功打开进程。可以在调用OpenProcess函数前使用其他方法验证进程的存在性,如使用EnumProcesses函数列举当前运行的进程并检查是否包含指定的进程。 4. 硬件或操作系统限制:某些情况下,例如特定的防护软件或操作系统限制,可能会导致OpenProcess函数失败。可以尝试禁用相关的安全软件或配置操作系统,以解决此问题。 总之,解决OpenProcess函数返回值为空的方法取决于具体的场景和问题原因。通过确认进程ID或句柄的正确性、提升权限、验证进程的存在性以及排除硬件和操作系统限制,可以帮助解决OpenProcess函数返回空值的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值