2014年7月2日 星期三

Hook CloseHandle时遇到程序退出时卡死的问题原因及解决方案

  实际上这个问题我很久之前就遇到过了,在Hook CloseHandle函数的情况下,点击关闭按钮后程序要等一段时间才能够关闭,当初只当是虚拟机性能差造成的延迟,直到前几天我在新公司写Hook代码在实机上测试才发现问题并不是我之前认为的那样。

问题现象:
  • 在Hook CloseHandle函数的情况下,点击关闭按钮后要等一段时间进程才能够退出。
问题原因:
  • 在程序退出的过程中,全局对象的生存期已经结束,系统在进行进一步收尾工作时调用了CloseHanle,这时在伪函数内访问了已经销毁的全局对象,导致异常产生。
解决方案:
  • 动态申请在伪函数内需要访问到的全局对象,将对象保存在堆内。
  此时对象保存在堆内而非栈内,在程序退出全局变量生存期结束时不会调用析构函数。同时,虽然用于保存该对象地址的指针/引用虽然也超过生存期,但是由于没有被复写,也不存在析构函数,所以可以访问。

分析过程:
  首先尝试在进程等待退出时间段内使用Process Explorer查看该进程各个线程的调用堆栈情况,初步判断原因。
  现象:一用Process Explorer查看该进程线程情况,一切换到该进程属性的Threads标签页程序立刻退出。
  现象分析:Process Explorer查询线程堆栈调用了dbghelp.dll内相关函数,可能程序遇到的情况如果不挂调试器就不继续执行了。
  尝试:先用Process Explorer查看该进程属性的Threads项,关闭程序,让异常现象产生
  现象:从调用堆栈可以看出,现场内存在未处理的异常。
  猜测:【猜测内容同问题原因】(运气不错,一下猜中了)
  编写粗糙的测试代码:
  BOOL bDestoryed = FALSE;
  Class fdsa{
  public:
    fdsa(){};
    ~fdsa(){bDestoryed = TRUE};
  }
  fdsa xxx;
    同时在CloseHandle的伪函数内判断bDestoryed是否被赋值为TRUE。

  最终确定猜测成立。

沒有留言:

張貼留言