我在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 的"大小为 1 的无效写入"错误。
知道为什么吗?
如果我将hex
向量增大两个字节(一个似乎还不够)
std::vector<char> hex(len + 2);
该错误从瓦尔格林德的报告中消失了。
因为你出局了一个。
如果iData
说"xy",那么end
指向"y"后面的一个。使用您的<= end
,您尝试将 3 个字符(给出 6 个十六进制数字)编码到一个仅足够容纳 4 的空格中。
您的问题是end
的一个错误。 您可以通过在C++中使用一些更高级别的概念来避免这种棘手的边缘情况,而不会降低运行时速度。 特别是,基于范围的for
和使用std::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({" ", 1}, "00")
+ test({" ", 2}, "0000")
+ test("377", "ff");
}
那是瓦尔格林德干净的。