memcpy ведет себя неожиданно

0

Ниже приведен мой пример кода:

int function1(unsigned char *out, int length){
unsigned long crypto_out_len = 16;
unsigned char crypto_out[16] = {0};
.......
//produces 16 bytes output & stores in crypto_out
crypto_function(crypto_out, crypto_out_len); 
//lets say crypto_output contents after are : "abcdefghijklmnop"
.......
memcpy(out, crypto_out,length);
return 0;
}

function2(){
unsigned char out[10] = {0};
function1(out, 10);
std::pair<unsigned char *,int> map_entry;
map_entry.first = out;
map_entry.second = 10;
}

Теперь map_entry.first должен содержать: "abcdefghij", правильно?

Но он содержит "abcdefghij # $% f1 ^", некоторый мусор, связанный с ним. Как избежать такого непредвиденного поведения, чтобы map_entry.first содержал именно "abcdefghij".

Теги:
pointers
memcpy
out-of-memory

2 ответа

1
Лучший ответ

Поскольку вы не вставляли весь код, я не могу быть на 100% уверенным, но я думаю, что знаю, что случилось. memcpy() ведет себя корректно здесь, и все на 100% определяется поведением.

В этом случае out является 10-символьной строкой без нулевого терминатора. Вы назначаете его unsigned char* который не содержит информации о длине, и я подозреваю, что вы просто не используете число десять, когда вы ссылаетесь на map_entry.first.

Если вы печатаете его как unsigned char* или строят с ним std::string, C++ ожидает, что это std::string с нулевым завершением. Поэтому он считывает его до первого нулевого символа. Теперь, так как out его не было он просто пробегает и начинает читать символы на стеке после out, который, случается, что вы видите, как мусор.

Что вам нужно сделать, убедитесь, что либо строка завершена с нулевым символом, либо убедитесь, что вы всегда ссылаетесь на нее, указав правильную длину. Для первого вы хотели бы out 11-байтный длинный и оставить последний байт как 0:

function2(){
    unsigned char out[11] = {0};
    function1(out, 10);
    std::pair<unsigned char *,int> map_entry;
    map_entry.first = out;
    map_entry.second = 10;
}

Также обратите внимание, что C++ фактически остановится на первом нулевом символе, с которым он сталкивается. Если ваш crypto_function() может вывести нулевые байты в середине строки, вы должны знать, что строка будет усечена в точке.

Для последнего вам нужно будет использовать функции, которые фактически позволяют вам указать длину строки и всегда передавать длину 10. Если вы всегда работаете с этим, вам не нужно беспокоиться о нулевом crypto_function() от crypto_function().

  • 0
    но чтобы убедиться, что memcpy копирует нулевые символы также из src в dest, верно?
  • 0
    Да. memcpy() копирует указанное количество байтов и не заботится о нулевых символах вообще. strcpy() и strncpy() останавливаются на нулевом символе.
1

Вы путаете char[] со строками. out не содержит ожидаемых данных, но не заканчивается 0, поэтому, если вы попытаетесь отобразить его в виде строки, может показаться, что он содержит дополнительные данные. Если данные на самом деле являются строками, вам нужно правильно оканчивать их.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню