发现奇怪的 std::wstring 问题(或 VS 2022 的 bug + 由于缺少构造而导致奇怪的大小和容量 0)。 它位于大型遗留 C/C++ 项目中。
最小(最短)可重现示例
std::wstring &hell = *(std::wstring*)calloc(sizeof(std::wstring), 1);
hell = L"a"; // hell contains quite random Unicode wchar then
hell
是 struct T
的成员,并且存在 T
的动态数组 + 它们经常被重新分配。
缩短的原始代码示例:
class T { public:
_tstring yyyName;
int a, b, c, d;
};
T *y = (T*)calloc(no, sizeof(T));
T *y = (T*)realloc(y, NumOfParams * sizeof(T));
问题应该是默认
_Small_string_capacity == 7
并且缺少构造。最快、最简单的修复,但可能不是最好的:
template<class T>
class lazyPtr {
public:
lazyPtr() {
_member = new T();
};
operator T&() {
if (!_member) _member = new T(); // construct missing string
return *_member;
};
T operator =(const T right) {
if (!_member) _member = new T(); // construct missing string
*_member = right;
return *_member;
}
~lazyPtr() {
delete _member;
};
private:
T *_member;
};
lazyPtr<std::wstring> fix = *(lazyPtr<std::wstring>*) // intended nonsense
calloc(sizeof(lazyPtr<std::wstring>), 1); // create uninitialized string again
fix = L"y";
除了大型重构或 C++ 解决方法(如此处所示的模板)之外,还有更好的选择吗?
唯一的解决方案是重构整个项目吗?用 new/delete/(copy/default) 构造函数替换 malloc/zeromem/calloc/free/memcpy 并使用向量而不是
T
结构数组?
没有最佳解决方案,只有特定情况下的最佳解决方案,而我们对此知之甚少。
我看到有两种方法可以摆脱你的情况:要么重构代码以使用惯用的C++(这确实需要在任何地方使用new
和
delete
——现在我们更喜欢智能指针),或者使用惯用的C和重构它使用 C 编译器来构建它。我无法告诉您根据您的具体情况哪种选择更好。我看不出上面的模板有什么意义,也看不出拥有指向 C++ 字符串或一般容器的指针。只需使用std::wstring hell = L"a";
。