一次vector析构异常的思考

转载 2011年01月24日 19:10:00

关键字:exe、dll、STL string、local heap。

  一个结构体 ITEM 中包含了多个 string 类型字段,在 exe 中的 ExeFunc 中定义 ITEM 变量 item,传 item 的引用到 DllFunc 函数中,DllFunc 是一个 dll 的导出函数,负责从文件中读取一些数据到 ITEM 结构中。在 ExeFunc 结束的时候 string 异常了,提示堆内存损坏。排除法发现多个 string 字段中只有一个引发了异常,其它的都没有问题,觉得很奇怪。string 异常的字段赋值的字符串大于 16 个字符(string 默认是15 还是 16 个 byte 来着)其它的都小于 16 个字符,显然是 string 对象重新分配内存了。

  查看内存也没有发现异常情况,怀疑 string 有问题,于是另外建了个工程测试 string,单个 exe 或者模拟工程中建立一个 dll 赋值给引用 string 变量都正常,而且字符数大于 16 个。

  跟踪定位到 _CrtIsValidHeapPointer ,注意到 dbgheap.c 文件中 _CrtIsValidHeapPointer 处注释:

         /*
         * If this ASSERT fails, a bad pointer has been passed in. It may be
         * totally bogus, or it may have been allocated from another heap.
         * The pointer MUST come from the 'local' heap.
         */

         _ASSERTE(_CrtIsValidHeapPointer(pUserData));

  搜索到一些关于本地堆(local heap)的文章,才明白是因为 dll 如果静态链接了运行时库,dll 就会拥有独立于应用程序堆(也称作local heap)的运行时堆实例。此时在 dll 外部就不能访问此 local heap,所以也就有上面所出现的异常啦。MSDN 中也有介绍:

  The _CrtIsValidHeapPointer function is used to ensure that a specific memory address is within the local heap. The local heap refers to the heap created and managed by a particular instance of the C run-time library. If a dynamic-link library (DLL) contains a static link to the run-time library, it has its own instance of the run-time heap, and therefore its own heap, independent of the application's local heap. When _DEBUG is not defined, calls to _CrtIsValidHeapPointer are removed during preprocessing.

  查找这个问题浪费了不少的时间,解决办法就是在编译 dll 时动态链接运行时库( VS2005 下动态链接 MFC 库默认就是动态链接运行时库,如果更改静态链接 MFC 库,运行时库的链接方式也跟着改变为静态的),并且 exe 中也要使用相同的链接方式才行。这或许是有时候改变 MFC 库的链接方式会引起一些莫名错误的原因吧;对了在 _CrtIsValidHeapPointer 内部也有这样的注释:

         /*
         * Go through the heap regions and see if the pointer lies within one
         * of the regions of the local heap.
         *
         * Pointers from non-local heaps cannot be handled. For example, a
         * non-local pointer may come from a DLL that has the CRT linked-in.
         *
         */

  结论:应用程序使用的 dll 库在链接时尽量使用相同的链接方式,大多数情况下不同的链接方式不会出现问题,但有少数情况总是存在的。额要是在第一时间看清楚明了的 MSDN 就不会走N多的弯路了:(

 

 

原文出处:http://hi.baidu.com/anowsober/blog/item/9c1abcd95d20b4ee38012f6b.html

相关文章推荐

如何解决vector 析构异常 opencv Assert _CrtIsValidHeapPointer

vector 析构异常 opencv Assert _CrtIsValidHeapPointer

vs 中opencv vector析构问题

来源:[VS+OpenCV] 程序运行过程正常,当跳出函数是出现断言错误vs2013 opencv vector析构时出错具体内容: 自己来回答了,原因其实很简单,却容易想不到。 出错的根本...

Vector::构造,复制构造,析构

构造函数:// 构造函数 Vector(int c = DEFAULT_CAPACITY, int s = 0, T v = 0) //容量为c、规模为s、所有元素初始为v { _elem...

[C++]exit & abort & 析构 & 异常

进程之死   对于一个用C++写的程序,被加载至内存后运行,最终走向死亡。程序的死亡大致有三种: 自然死亡,即无疾而终,通常就是main()中的一个return 0;自杀,当程序发现自己再活下去已...

Effective C++条款8,9析构中的异常和虚拟函数

条款8:别让异常逃离析构函数 析构函数的作用就是清理资源等后续工作,一旦这里发生异常就会产生严重后果。所以在编写析构函数时要格外小心。 如 class Widget{ public: ... ~Wid...

C++异常处理catch()中变量析构与构造的奇怪问题

一直对C++中的try catch结构非常的疑惑。 编写了如下代码来查看被throw的对象,怎样被catch到的。 // test.cpp : 定义控制台应用程序的入口点。 // #incl...

异常栈展开和对象析构

1、函数调用链 函数与子函数之间的调用关系可以用一个链来表示,调用连,相关的一个重要数据结构就是栈帧,子函数返回的时候,栈展开,构造在栈上的对象被编译器设置的析构函数析构销毁。  函数调用  ...

成员变量指针未初始化,异常处理对象析构

前些天KsSuperGraphEx的BUG很是晕人,其崩溃原理也比较罕见,特发文存档。 下面是一些代码: // VC: Debug #include class CData {...

C++异常(5) - 异常处理与对象析构

预测下面程序输出结果: #include using namespace std; class Test { public: Test() { cout << "Constructing an ...

构造析构顺序.rar

  • 2008-10-21 19:35
  • 329KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)