Valgrind:&#34;写入大小为1&#34;在char []到std :: vector <char>之后

时间:2017-02-03 08:40:15

标签: c++ hex std valgrind heap-memory

我在c ++中有一个非常简单的hexlify方法,它基于python的binascii实现。

std::string Hexlify(const std::string& iData)
{
    // the same as python binascii.b2a_hex
    const size_t len = iData.size() << 1; // output will be twice as long
    char hex[len];

    const char* curdata = iData.data();
    char* curhex = hex;
    const char* end = curdata + iData.size();

    char c;
    // from python's implementation (2.7.1, if it matters)
    while(curdata <= end)
    {
        c = (*curdata>>4) & 0xf;
        c = (c>9) ? c+'a'-10 : c + '0';
        *(curhex++) = c;
        c = (*curdata) & 0xf;
        c = (c>9) ? c+'a'-10 : c + '0';
        *(curhex++) = c;
        curdata++;
    }
    return std::string(hex, len);
}

这完全没问题。

现在,hex char []被分配到堆栈上,处理大量缓冲区时可能会出现问题,这就是为什么我要将它迁移到std::vector以从堆分配中受益的原因

std::string Hexlify(const std::string& iData)
{
    // the same as python binascii.b2a_hex
    const size_t len = iData.size() << 1; // output will be twice as long
    std::vector<char> hex(len);

    const char* curdata = iData.data();
    char* curhex = &hex[0];
    const char* end = curdata + iData.size();

    // SAME CODE AS BEFORE

    return std::string(&hex[0], len);
}

这个std::vector实现会生成一个Valgrind&#34;无效的写入大小为1&#34;错误。

知道为什么吗?

如果我使hex向量的两个字节更大(一个似乎不够)

std::vector<char> hex(len + 2);

错误从valgrind的报告中消失。

2 个答案:

答案 0 :(得分:3)

因为你被一个人拒之门外。

如果iData说&#34; xy&#34;,则end指向&#34; y&#34;之后的一个。使用<= end,您尝试将3个字符(给出6个十六进制数字)编码到一个仅足够4的空间中。

答案 1 :(得分:0)

您的问题是end的一个错误。通过在C ++中使用一些更高级别的概念,可以避免这种棘手的边缘情况,而不会影响运行时速度。特别是,基于范围的forstd::string作为标准容器的使用意味着我们可以实现这一点而不需要边界测试或指针算法来解决错误:

#include <string>

std::string hexlify(const std::string& s)
{
    static auto const to_hex = [](char c)
        {
            c &= 0xf; return c>9 ? c+'a'-10 : c+'0';
        };

    std::string result;
    result.reserve(2 * s.size());

    for (auto b: s) {
        result.push_back(to_hex(b>>4));
        result.push_back(to_hex(b));
    }
    return result;
}


int main()
{
    static auto const test = [](const std::string& in,
                                const std::string& expected)
        {
            return hexlify(in) != expected;
        };

    // We use numeric character escapes to avoid dependence on any
    // specific character coding.
    return test("\60", "30")
        +  test({"\0\0", 1}, "00")
        +  test({"\0\0", 2}, "0000")
        +  test("\377", "ff");
}

这是Valgrind-clean。