(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源)
添加注意@2022:
本篇文档遇到的问题,是基于VS特定版本源码分析的,使用的版本是VS2008,平台工具集V90。如果非这个版本的话,源码分析部分并不相同。
也检查了平台工具集VS100,VS141版本,虽然vector源码实现不同,但这几个版本也有类似情况;同时在平台工具集VS141版本,string在debug与release版本上,也同vector一样,debug版多了一个_Container_proxy变量。
有疑问的话,都可以使用下面的语句来检查,看看release版本与debug版本打印的结果,来明确两者结构体是否有差异:
printf("size of empty vector<int>: %d\n", sizeof(std::vector<int>));
如果你调用dll中的函数,使用了vector传递参数时,报错“vector的size异常,长度超限” 代码位置 “_THROW(length_error, "vector<T> too long")”
那么你可能遇到了vector的debug版与release版不匹配问题。
在未作条件编译情况下,如果:
1. 调用程序使用debug版本vector
2. Dll中使用release版本vector
则传递空的vector,会出现这个问题(当然了,传递非空vector也应该是有问题的)
问题产生的原因是:
VS中的STL的debug版本与release版本vector在内存分配上是有差别的,从而导致两边数据结构不一致,赋值的时候出现内存溢出相关问题。从而被误认为vector长度超限问题。
问题详细原因可以通过查看VS中vector的代码:
1. Vector继承自_Vector_val
typedef _Vector_val<_Ty, _Ax> _Mybase;
explicit vector(const _Alloc& _Al)
: _Mybase(_Al)
2. _Vector_val继承自_CONTAINER_BASE_AUX_ALLOC
_Vector_val(_Alloc _Al = _Alloc())
: _CONTAINER_BASE_AUX_ALLOC<_Alloc>(_Al), _Alval(_Al)
3. 跟踪看到,在Debug和Release时,分别走了不同的分支
#if !_HAS_ITERATOR_DEBUGGING && (defined(_DEBUG) || _SECURE_SCL)
// We have an aux object.
#define _CONTAINER_BASE_AUX_ALLOC _Container_base_aux_alloc_real
#else
// We don't have an aux object.
#define _CONTAINER_BASE_AUX_ALLOC _Container_base_aux_alloc_empty
#endif
而在_Container_base_aux_alloc_real(继承自_Container_base_aux)中有一个变量
_Aux_cont * _Myownedaux;
但在_Container_base_aux_alloc_empty(继承自_Container_base)是没有这个变量的。
查看宏定义中:
#if !defined (_HAS_ITERATOR_DEBUGGING)
#if defined (_DEBUG)
#define _HAS_ITERATOR_DEBUGGING 1 /* for range checks, etc. */
#else
#define _HAS_ITERATOR_DEBUGGING 0
#endif /* defined (_DEBUG) */
#else
#if !defined (_DEBUG) && _HAS_ITERATOR_DEBUGGING != 0
#include <crtwrn.h>
#pragma _CRT_WARNING( _NO_ITERATOR_DEBUGGING )
#undef _HAS_ITERATOR_DEBUGGING
#define _HAS_ITERATOR_DEBUGGING 0
#endif
#endif /* !defined (_HAS_ITERATOR_DEBUGGING) */
#if !defined (_SECURE_SCL)
#define _SECURE_SCL 1
#endif
我这边调试时看到:
Release版本走了分支_Container_base_aux_alloc_real。
Deubg版本走了分支_Container_base_aux_alloc_empty。
从上面可以看出,这个实际上是跟VS中STL实现有很大关系的,VS中的调试相关机制的依赖,使得debug/release版本数据结构上存在差异。
VS141版本检查到的差异部分实现在这个位置:vector中使用变量,在Release时继承自_Container_base0,在Debug版本继承自_Container_base12
#if _ITERATOR_DEBUG_LEVEL == 0
using _Container_base = _Container_base0;
using _Iterator_base = _Iterator_base0;#else /* _ITERATOR_DEBUG_LEVEL == 0 */
using _Container_base = _Container_base12;
using _Iterator_base = _Iterator_base12;
#endif /* _ITERATOR_DEBUG_LEVEL == 0 */...template<class _Val_types>
class _Vector_val
: public _Container_base{...}...
template<class _Ty,
class _Alloc = allocator<_Ty>>
class vector
: public _Vector_alloc<_Vec_base_types<_Ty, _Alloc>>{...
_Compressed_pair<_Alty, _Vector_val<_Val_types>> _Mypair;
...}
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源)