未定义行为,因为 std::wstring 未正确构造。遗留代码的最佳修复是什么?

问题描述 投票:0回答:1

发现奇怪的 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
并且缺少构造。
分析“bug”细节可能没有意义。


最快、最简单的修复,但可能不是最好的:

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++ widestring
1个回答
0
投票

没有最佳解决方案,只有特定情况下的最佳解决方案,而我们对此知之甚少。

我看到有两种方法可以摆脱你的情况:要么重构代码以使用惯用的C++(这确实需要在任何地方使用new

delete
——现在我们更喜欢智能指针),或者使用惯用的C和重构它使用 C 编译器来构建它。我无法告诉您根据您的具体情况哪种选择更好。
我看不出上面的模板有什么意义,也看不出拥有指向 C++ 字符串或一般容器的指针。只需使用

std::wstring hell = L"a";

    

© www.soinside.com 2019 - 2024. All rights reserved.