Помимо смежных проблем хранения и ясности кода, я столкнулся с некоторыми довольно коварными ошибками, пытаясь использовать std::string
для хранения необработанных байтов.
Большинство из них были сосредоточены на попытке преобразовать массив байтов char
в std::string
при взаимодействии с библиотеками Си. Например:
std::string password = "pass\0word";
std::cout << password.length() << std::endl; // prints 4, not 9
Может быть, вы можете исправить это, указав длину:
std::string password("pass\0word", 0, 9);
std::cout << password.length() << std::endl; // nope! still 4!
Вероятно, это связано с тем, что конструктор ожидает получения C-строки, а не байтового массива. Возможно, есть лучший способ, но я закончил с этим:
std::string password("pass0word", 0, 9);
password[4] = '\0';
std::cout << password.length() << std::endl; // hurray! 9!
Немного неуклюже. К счастью, я нашел это в модульном тестировании, но я бы пропустил его, если бы в моих тестовых векторах не было нулевых байтов. Что делает это коварным, так это то, что второй вышеописанный подход будет работать нормально , пока массив не будет содержать нулевой байт.
Пока что std::vector<uint8_t>
выглядит хорошим вариантом (спасибо Дж. Н. и Хюркилу):
char p[] = "pass\0word";
std::vector<uint8_t> password(p, p, p+9); // :)
Примечание. Я не пробовал конструктор итератора с std::string
, но эта ошибка достаточно проста, чтобы ее можно было избежать даже при такой возможности.
Извлеченные уроки:
- Методы обработки тестовых байтов с тестовыми векторами, содержащими нулевые байты.
- Будьте осторожны, когда (и я бы сказал, избегать) использовать
std::string
для хранения необработанных байтов.