在std :: vector <unsigned char =“”>中将std :: wstring编码为UTF-16的正确方法是什么?

时间:2016-03-14 15:49:33

标签: c++ c++11 encoding utf-16

我试图将std::wstring编码为UTF-16并将其传递给一个带有一对向量迭代器的函数。为此,我尝试了以下内容。

std::vector<unsigned char> HashAlgorithm::ComputeHash(std::wstring value)
{
    std::wstring_convert<std::codecvt_utf16<wchar_t>> converter;

    std::string encodedString = converter.to_bytes(value);

    std::vector<unsigned char> encodedBytes(
        reinterpret_cast<unsigned char const *>(encodedString.c_str()),
        reinterpret_cast<unsigned char const *>(encodedString.c_str() + encodedString.size()));

    std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(), encodedBytes.end());
    return hashedBytes;
}

它在大多数情况下工作正常,除了我知道有些错误,因为在调试模式下,我在hashedBytes的返回时看到以下断言,这有点像某种堆栈损坏。

Debug Assertion - _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

导致此错误的原因是什么?如何预防?

编辑#1

以下是我正在使用的支持功能的内容。我一直试图将其分解以找出断言的起源和原因,但我还没有能够获得最小的再现。

std::vector<unsigned char> HashAlgorithm::ComputeHash(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
    this->Process(begin, end);
    std::vector<unsigned char> hashedBytes = this->Complete();

    return hashedBytes;
}

void HashAlgorithm::Process(std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
{
    NTSTATUS status = BCryptHashData(this->hash, const_cast<unsigned char *>(&(*begin)), std::distance(begin, end), 0);
}

std::vector<unsigned char> HashAlgorithm::Complete()
{
    std::vector<unsigned char> result(this->outputSize);

    NTSTATUS status = BCryptFinishHash(this->hash, result.data(), (ULONG)result.size(), 0);
    return result;
}

2 个答案:

答案 0 :(得分:1)

Microsoft VC ++ 2010和2015之间的

std::wstring 向后兼容。

问题是库代码(VS 2010)中的std::wstring和客户端代码(VS 2015)的大小差异为4个字节。较新版本的std::wstring较大,为32字节,而较旧版本为28字节。当通过值传递这些变量时,堆栈损坏发生在较小的std::wstring的前4个字节中,并触发用于防止基于堆栈的漏洞的堆栈canaries。

答案 1 :(得分:0)

为了确保您不会丢失任何数据,您应该直接散列字节:

std::vector<unsigned char> myClass::ComputeHash(std::wstring value)
{
    auto size_of_data = value.size()*sizeof(value[0]);
    auto pointer_to_data = reinterpret_cast<unsigned char const *>(value.data());
    std::vector<unsigned char> encodedBytes(pointer_to_data,pointer_to_data+size_of_data);
    std::vector<unsigned char> hashedBytes = this->ComputeHash(encodedBytes.begin(),encodedBytes.end());
    return hashedBytes;
}

尝试添加香蕉(\ U0001F34C),以便在您单步执行时查看数据会发生什么。例如std::wstring my_unicode_string{L"Test string \n"};std::wstring wstr = L"z\u00df\u6c34\U0001F34C"; // L"zß水"。如果你的.cpp文件没有保存为unicode文本,那么第二个例子可能会更好。

to_bytes可能会引发异常,因为只有基本多语言平面中的代码点才能编码为单个wchar。如果它确实为你做了转换,它可能已经将不同的更高代码点映射到类似的字节,这将导致不同字符串的相同散列。