摘要:
有一个dll库是使用vs2010编译的, 使用这个dll动态库的工程是vs2019. 这个dll动态库返回一个结构体,其中有个成员使用了std::string。但是遇到了std::string的成员显示被赋值为NULL的情况。
本文对进行分析, 重点在于追踪问题的思路。
问题描述:
- dll使用vs2010编译
- dll动态库返回一个结构体,其中有个成员使用了std::string
- 使用dll的工程是vs2019, 出现该std::string成员被赋值为NULL。
- 但是使用vs2010工程就没错误。
- 问题现象:
问题分析:
一. 分析该成员访问的偏移量
vs2019
vs2010
二. 对比成员 description 的访问地址偏移的分析
typedef std::string CVHString;
CVHString pointName; // 测点名
CVHString interfaceName; // 采集器名
CVHString unitName; // 量程单位
CVHString description; // 描述
- 访问pointName时候, vs2019和vs2010, 地址都是 ecx,28h
- 访问description时
- vs2019是 edx, 70h
- vs2010是 edx, 7ch
- 两者相差16进制的C, 也就是12
- 中间相差三个变量,也就是 12/3 = 4
- vs2019的std::string,比vs2010的std::string,少了4个字节
三. vs2019的std::string相比vs2010的std::string缺少的四个字节的来源
vs2019
union _Bxty { // storage for small buffer or pointer to larger one
_CONSTEXPR20_CONTAINER _Bxty() noexcept : _Ptr() {} // user-provided, for fancy pointers
_CONSTEXPR20_CONTAINER ~_Bxty() noexcept {} // user-provided, for fancy pointers
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
char _Alias[_BUF_SIZE]; // TRANSITION, ABI: _Alias is preserved for binary compatibility (especially /clr)
} _Bx;
size_type _Mysize = 0; // current length of string
size_type _Myres = 0; // current storage reserved for string
vs2010
union _Bxty
{ // storage for small buffer or pointer to larger one
_Elem _Buf[_BUF_SIZE];
_Elem *_Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
size_type _Mysize; // current length of string
size_type _Myres; // current storage reserved for string
_Alty _Alval; // allocator object for strings
四. vs2010的std::string中的_Alty的定义
typedef typename _Alloc::template rebind<_Elem>::other _Alty;
template<class _Other>
struct rebind
{ // convert this type to _ALLOCATOR<_Other>
typedef _ALLOCATOR<_Other> other;
};
pointer address(reference _Val) const
{ // return address of mutable _Val
return ((pointer) &(char&)_Val);
}
const_pointer address(const_reference _Val) const
{ // return address of nonmutable _Val
return ((const_pointer) &(char&)_Val);
}
结论:
- vs2010中的std::string, 存在成员 _Alty _Alval; // allocator object for strings
- 但是这个成员,在vs2019的 std::string 中,被删除了。
- 导致vs2019的std::string 比 vs2010的std::string 少了四个字节