Ниже приведен мой пример кода:
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".
Поскольку вы не вставляли весь код, я не могу быть на 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()
.
Вы путаете char[]
со строками. out
не содержит ожидаемых данных, но не заканчивается 0, поэтому, если вы попытаетесь отобразить его в виде строки, может показаться, что он содержит дополнительные данные. Если данные на самом деле являются строками, вам нужно правильно оканчивать их.
memcpy()
копирует указанное количество байтов и не заботится о нулевых символах вообще.strcpy()
иstrncpy()
останавливаются на нулевом символе.