C++代码中 栈溢出错误 chkstk.asm 一则

Posted on 2009-12-31 12:04  blackcat  阅读(9200)  评论(1编辑  收藏  举报

  日前,项目组做一个通信组件,用C++开发,有项目组老大做设计和主要开发,同时他自己完成C++的封装和Python的封装,由于他对Java不熟悉,故找了一个Java的兄弟来做。

  以上是背景。

  按我的理解从技术角度评价下其中涉及到的人员:

  A,项目组老大,C++开发出身,为公司负责过一套产品,在软件设计上颇有想法,C++甚是熟练,受MFC影响较深,水平很高。但是对于系统深层的特性不太了解,比如对象内存布局,字符资源内存分布等,均犯过一些低级错误,正好都是我帮他解决,故了解一点。

  B,Java开发人员,新手,对Java非常了解,但是由于一直接触Java,被Java封装的不太明白Java之外的事态万千。对Natice Code了解不多,仅限于能够运行起来,也是不了解更底层一点的机制。

  

  B兄弟搞了一段时间,决定使用JNA来做,觉得JNA比较合适,对于Java开发人员要求比较低。我开始不知道有JNA,后来查了下,觉得确实不错 (JNA官方主页)。但是B兄弟使用JNA对A老大的C++ Client调用时候,总是莫名其妙的崩溃,经过一段时间破茧的过程,哥们撑不住了,找我帮忙。我对于Java了解不多,但是简单Java程序还是没有问题的(现在对于任何语言,我估计一个差不多点的程序员都有这个程度,故平时最不喜欢看到有人说我不懂这个,你看看吧),但是我没有看B兄弟的代码,因为我需要自己实践下JNA,了解下更多细节。我自己写了个C++多线程,一个线程中回调JNA中传入的回调函数指针,顺利通过。但是同样的代码,调用A老大的dll,就导致栈溢出。

  对于这个栈溢出,我一直以为是某些指针越界造成,没有太多想,就把A老大的代码拿来调试了下,结果发现两个问题。第一个,回调指针的值,居然在一个函数传递过程中自己改变了(win debug模式),第二个,回调触发时候,程序由于溢出崩溃。

  瞎整了半天之后,还是老老实实打开反汇编一步步看回调过程中发生了什么,居然在回调后,所有参数入栈后,调用chkstk.asm崩溃了,我晕倒,这个问题居然,回过头看C++代码,找找有啥大对象在栈里面晃悠,结果一看,居然有几处使用的是char[64*1024]的形式,这几处正好在一个函数调用中都递归了,于是光荣的越界了。于是修改那几处缓冲到堆上,问题解决了。

 

  下面说下我对于char[size]形式的理解,由于char[]是编译期间分配内存的行为,估计对于一些耗用资源不大的调用,当然首先char[]的形式,但是如果需要的内存比较大,还是取堆中取,防止栈空间不足的崩溃。

  我的习惯风格:

  static const int N_MAX_STACK_BUFFER = 128;

  

  TCHAR szBuffer[128] = {0};

  TCHAR * pBuffer = szBuffer;

  int nSize = GetBufferSize();

  if (nSize >= N_MAX_STACK_BUFFER)

  {

     pBuffer = new TCHAR[nSize];

  }

 

  // Action

 

  if (nSize >= N_MAX_STACK_BUFFER)

  {

    delete [] pBuffer;

    pBuffer = NULL;

  }

 

  至此,第二个问题解决,但是第一个问题很诧异,也没有崩溃现象,怀疑是Debug作祟,切换到Release,把地址答应出来,OK,都正常了。这个VC的编译器还是比较邪门的。

  另外,发现自己行文中闲扯真多。不是好习惯。

Copyright © 2024 blackcat
Powered by .NET 9.0 on Kubernetes