C++程序调用IsBadReadPtr或IsBadWritePtr引发内存访问违例问题的排查

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++程序调用IsBadReadPtr或IsBadWritePtr引发内存访问违例问题的排查相关的知识,希望对你有一定的参考价值。

目录

1、问题描述

2、VS中看不到有效的信息,尝试使用Windbg去分析

3、使用Windbg分析

4、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931       最近在用VS调试程序时老是遇到程序一启动就报错的问题,严重影响软件新功能的开发进度,于是就详细地研究了一下。经分析,发现是因为程序依赖的某个比较老的第三方库调用了IsBadReadPtr和IsBadWritePtr这两个微软已经废弃的老接口导致的。下面将整个问题的分析过程分享出来,以供大家借鉴或参考。 

1、问题描述

        某天,在Visual Studio(以下简称VS)中调试Debug版本程序,刚启动调试就弹出如下的报错提示框:

报出0xC0000005内存访问违例,是在读取某个内存地址时发生了内存读违例(试图去访问一个不应该或者没权限访问的内存)。

       因为当前是在VS中进行Debug调试,所以可以直接切换到call stack函数调用堆栈页面去查看此时的函数调用堆栈:

但并没有看到有效的函数调用堆栈,只能在堆栈中看到异常发生在kernel32.dll系统库模块中。这个有点奇怪,之前几天启动Debug调试时都是正常的,为啥今天突然会报错,并且是必现的。 

2、VS中看不到有效的信息,尝试使用Windbg去分析

        同样的代码,同样的底层dll库,为啥不同时间点表现不一致呢(有时报异常,有时又不报异常)?经尝试发现,在VS的调试状态下,多次按下F5继续运行之后,可以将这个异常跳过去。所以,这个报错不是致命性的异常,是可以跳过去的,然后程序还可以继续运行。

       除了多次按下F5将异常跳过,也可以在弹出的报错提示窗口中,勾除掉“引发此异常类型时中断“,下次就不会再报这类异常了:

       一般当我们在VS中看不到有效的异常上下文信息(比如有效的函数调用堆栈)时,可以尝试使用Windbg直接启动程序或者将Windbg附加到已经运行的目标进程上,看看能否看到有效的函数调用堆栈信息等信息。

       对于本案例,报错是发生在程序启动时,所以需要使用Windbg启动目标程序,这样Windbg才能感知到启动时的异常。因为异常发生在程序启动的过程中,要等目标程序启动起来后再将Windbg附加到目标进程上,时机上就晚了。 

3、使用Windbg分析

       于是用Windbg启动Debug版本的exe程序,启动后,Windbg果然监测到0xC0000005内存访问违例异常,如下所示:

从上图可以看到是调用kernel32!IsBadReadPtr接口触发的,然后输入kn命令查看此时的函数调用堆栈,从堆栈中可以看到是底层的HKCommand模块中的HKGetSerialNum接口中调用了IsBadReadPtr。可以执行g命令将此异常跳过去,但会多次报该异常(应该是多次调用了IsBadReadPtr函数),多次g就可以了。

       对于IsBadReadPtr,有经验的人可能知道这个系统API,同类型的API接口还有IsBadWritePtr。在以前,IsBadReadPtr用来判断目标内存地址是否可读,IsBadWritePtr用来判断目标内存地址是否可写,但现在这两个函数已经被废弃了,已经达不到预定的作用了!可以在微软在线MSDN上查看到这两个API函数的说明:

这两个API函数已经被废弃了,不建议再使用了,这两个函数不能判断出目标地址是否可读可写。

       在本问题中,是HKCommand.dll库中函数内部调用了IsBadReadPtr接口,这个HKCommand.dll库是第三方安全相关的库,这个库比较老(可能是好几年前的库),在老版本库的代码中调用IsBadReadPtr或者IsBadWritePtr是有可能的。

4、最后

       本文简单介绍了由IsBadReadPtr函数调用引发异常的排查过程,整个分析过程也相对比较简单,主要给大家提供一个借鉴或参考。    

以上是关于C++程序调用IsBadReadPtr或IsBadWritePtr引发内存访问违例问题的排查的主要内容,如果未能解决你的问题,请参考以下文章

DelphiLinux版的IsBadReadPtr

R语言vtreat包自动处理dataframe的缺失值并生成对应的数据列_isbad来指示数据的原始缺失情况查看特定字段缺失的那些数据行查看数据集中多个字段的均值

从 C# 应用程序调用 C++ 代码或移植它?

从本机 C++ 调用 C#,而不使用 /clr 或 COM?

如何使 libcurl C++ 调用超时和/或知道调用中何时发生超时

是啥导致在单元测试(NUnit 或 MSTest)中从 C# 调用的 C++ 函数与在控制台应用程序中运行的相同代码产生不同的结果?