我在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的报告中消失。
答案 0 :(得分:3)
因为你被一个人拒之门外。
如果iData
说&#34; xy&#34;,则end
指向&#34; y&#34;之后的一个。使用<= end
,您尝试将3个字符(给出6个十六进制数字)编码到一个仅足够4的空间中。
答案 1 :(得分:0)
您的问题是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({"\0\0", 1}, "00")
+ test({"\0\0", 2}, "0000")
+ test("\377", "ff");
}
这是Valgrind-clean。