std::vector传递dll参数异常-长度超限

89 篇文章 5 订阅

(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 转载请标明来源)

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春夜喜雨

稀罕你的喜欢!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值