导出类包括STL(vecter/map等)成员变量引发的异常

沪深300ETF即将上市,现有业务系统有些数据逻辑要调整。于是就有这么个导出的窗口类(选择数据的,很多地方有用到)需要优化,一顿操作猛如虎,搞定!万万没想到,Release出来,弹出窗口,数据处理正常,操作后关闭,整个程序直接挂了,连个dump都没留。

开始排查问题。

1、VS切换到Debug模式,DoModal()后,选择数据后窗口自动关闭,弹出异常:
Run-Time Check Failure #2 - Stack around the variable 'xxx' was corrupted
也就是说,窗口的部分堆栈被破坏。两张可能,一是数据传输问题,二是资源释放异常。

2、再次试运行后,直接关闭窗口,同样弹出异常。那么数据传输是没问题的,最有可能就是资源释放异常。检查相关资源释放的地方,没什么问题。

3、那么回到成员数据上来。数据变动主要包括原有的一个map成员,然后又新增了几个map成员,再就是相关的逻辑改动。注释掉关键部分,不处理数据,发现异常依然存在。那就是和数据处理没关系了。呵,有点意思。

4、就剩下这几个变量了。突发奇想,移到类外怎样。然后…异常消失了!这么说,异常确实和这几个map变量有关。但是为什么?这其中并没有内存异常问题,堆栈破坏从何而来?事情变得更有意思(莫名其妙)了!

5、上一版本同样有个map变量,怎么就没问题呢?带着这个疑问,在窗口类中声明了一个map变量。运行,没有异常。然后,再声明一个map变量,异常出现!也就是说,这个导出窗口类中有两个以上map变量会异常

带着疑问去问度娘,一个大致的结论:从类导出STL,不能导出除std :: vector以外的任何内容。 参见微软的一篇文章:How To Exporting STL Components Inside & Outside of a Class

具体的解释:
大部分C++标准库里提供的类直接或间接地使用了静态变量。由于这些类是通过模板扩展而来的,因此每个可执行映像(通常是.dll或.exe文件)就会存在 一份只属于自己的、给定类的静态数据成员。当一个需要访问这些静态成员的类方法执行时,它使用的是“这个方法的代码当前所在的那份可执行映像”里的静态成 员变量。由于两份可执行映像各自的静态数据成员并未同步,这个行为就可能导致访问违例,或者数据看起来似乎丢失或被破坏了。

参考链接:

  1. Microsoft Visual Studio .NET 2003 Warning C4251
  2. (C++) Importing explicitly instantiated template class from dll
  3. 从dll导出包含std :: objects(vector,map等)的类(Exporting classes containing std:: objects (vector, map, etc) from a dll)
  4. 一个减少外部可见成员的数量的方法:Pimpl Idiom
  5. DLL中传递STL参数,vector对象作为dll参数传递等问题
  6. Discussion: Export class with STL member

你可能感兴趣的:(Windows,C++,爬坑记)