C ++ Преобразование двоичных данных в шестнадцатеричную строку и обратно - PullRequest
1 голос
/ 09 сентября 2011

У меня есть совпадающая пара статических функций в служебном классе, который я использую для преобразования двоичных данных (символы без знака) и их строкового представления (a-f и 0-9). Казалось, что они работают правильно, но недавно я попытался скомпилировать свой код под Visual C ++ (2010 Express), и, к моему ужасу, они вызывают только кучные ошибки повреждения. Что я делаю не так?

void Utility::string_to_binary(const std::string source, unsigned char* destination, unsigned int length)
{
    unsigned int effective_length = min(length, (unsigned int) source.length() / 2);
    for(unsigned int b = 0; b < effective_length; b++)
    {
        sscanf(source.data() + (b * 2), "%02x", (unsigned int*) &destination[b]);
    }
}

void Utility::binary_to_string(const unsigned char* source, unsigned int length, std::string& destination)
{
    destination.clear();
    for(unsigned int i = 0; i < length; i++)
    {
        char digit[3];
        sprintf(digit, "%02x", source[i]);
        destination.append(digit);
    }
}

Редактировать: Вот полная программа, которая иллюстрирует проблему.

#include <iostream>
#include <hdcs/Utility.h>

using namespace std;

int main(int argc, char* argv[])
{
    //Generate some data
    unsigned int size = 1024;
    unsigned char* data = new unsigned char[size];

    //Convert it to it's string representation
    string hex;
    Utility::binary_to_string(data, size, hex);

    //Output it to the screen
    cout << hex << endl;

    //Clear the data buffer
    memset(data, 0, sizeof(unsigned char) * size);

    //Convert the hex string back to binary
    Utility::string_to_binary(hex, data, size);

    //Cleanup
    delete[] data;
}

Ошибка возникает на delete[] data.

Ответы [ 3 ]

3 голосов
/ 09 сентября 2011

Ваш sscanf запишет unsigned int в область памяти, которую вы ему дадите.Обычно unsigned int имеет длину 4 или 8 байтов, в то время как вы намереваетесь предоставить только 1 байт.Таким образом, в конце концов, вы работаете над концом вашего динамического массива.

Кстати, ваш код очень далек от современного идиоматического C ++ - по сути, это просто прославленный C-беспорядок.Я настоятельно рекомендую переписать его в духе C ++.

2 голосов
/ 09 сентября 2011

Я бы переписал код, чтобы фактически использовать средства C ++ (на самом деле не проверял, просто идея):

std::vector<unsigned char> string_to_binary(const std::string& source)
{
    static int nibbles[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 };
    std::vector<unsigned char> retval;
    for (std::string::const_iterator it = source.begin(); it < source.end(); it += 2) {
        unsigned char v = 0;
        if (std::isxdigit(*it))
            v = nibbles[std::toupper(*it) - '0'] << 4;
        if (it + 1 < source.end() && std::isxdigit(*(it + 1)))
            v += nibbles[std::toupper(*(it + 1)) - '0'];
        retval.push_back(v);
    }
    return retval;
}

std::string binary_to_string(const std::vector<unsigned char>& source)
{
    static char syms[] = "0123456789ABCDEF";
    std::stringstream ss;
    for (std::vector<unsigned char>::const_iterator it = source.begin(); it != source.end(); it++)
        ss << syms[((*it >> 4) & 0xf)] << syms[*it & 0xf];

    return ss.str();
}
2 голосов
/ 09 сентября 2011

В этом коде

for(unsigned int b = 0; b < effective_length; b++)
{
    sscanf(source.data() + (b * 2), "%02x", (unsigned int*) &destination[b]);
}

вы, кажется, пишете unsigned int в местах destination, destination+1, destination+2 и т. Д.По мере приближения к последним байтам вашего destination буфера вы будете писать за его пределами.

Для примера, давайте предположим, что получатель является четырехбайтовым буфером, а sizeof (unsigned int)4 в вашей среде.Затем каждый sscanf записывает четыре байта.

Первая итерация записывает байты 0, 1, 2, 3

Вторая итерация записывает байты 1, 2, 3, 4

Третья итерация записывает байты 2, 3, 4, 5

Последняя итерация записывает байты 3, 4, 5, 6

Поскольку в буфере было всего четыре байта для начала, вынаписал за пределами вашего буфера.Бум.

РЕДАКТИРОВАТЬ

Ниже приведены минимальные изменения, необходимые для избежания этой конкретной ошибки:

for(unsigned int b = 0; b < effective_length; b++)
{
    unsigned int ui;
    sscanf(source.data() + (b * 2), "%02x", &ui);
    destination[b] = ui;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...