Инициализация указателя? для конкретной функции
-
22-07-2019 - |
Вопрос
Хорошо, это меня немного озадачило.
следующая функция кодирует строку в базу 64
void Base64Enc(const unsigned char *src, int srclen, unsigned char *dest)
{
static const unsigned char enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *cp;
int i;
cp = dest;
for(i = 0; i < srclen; i += 3)
{
*(cp++) = enc[((src[i + 0] >> 2))];
*(cp++) = enc[((src[i + 0] << 4) & 0x30)
| ((src[i + 1] >> 4) & 0x0f)];
*(cp++) = enc[((src[i + 1] << 2) & 0x3c)
| ((src[i + 2] >> 6) & 0x03)];
*(cp++) = enc[((src[i + 2] ) & 0x3f)];
}
*cp = '\0';
while (i-- > srclen)
*(--cp) = '=';
return;
}
Теперь о функции, вызывающей Base64Enc (), у меня есть:
unsigned char *B64Encoded;
Какой аргумент я передаю на unsigned char * dest в функции кодирования base 64. Я пробовал разные инициализации от mallocs до NULL для другой инициализации. Независимо от того, что я делаю, я всегда получаю исключение, и если я его не инициализирую, то компилятор (компилятор C VS2005) выдает предупреждение о том, что оно не было инициализировано. Если я запускаю этот код с неинициализированной переменной, иногда он работает, а некоторые другие - нет. Как мне инициализировать этот указатель и передать его функции?
Решение
вам нужно выделить достаточно большой буфер для размещения закодированного результата. Либо выделите его в стеке, например так:
unsigned char B64Encoded[256]; // the number here needs to be big enough to hold all possible variations of the argument
Но с помощью этого подхода легко вызвать переполнение стекового буфера, выделяя слишком мало места. Было бы намного лучше, если бы вы разместили его в динамической памяти:
int cbEncodedSize = srclen * 4 / 3 + 1; // cbEncodedSize is calculated from the length of the source string
unsigned char *B64Encoded = (unsigned char*)malloc(cbEncodedSize);
Не забудьте освободить () выделенный буфер после того, как вы закончите.
Другие советы
Похоже, вы хотели бы использовать что-то вроде этого:
// allocate 4/3 bytes per source character, plus one for the null terminator
unsigned char *B64Encoded = malloc(srclen*4/3+1);
Base64Enc(src, srclen, B64Encoded);
Будет полезно, если вы предоставите ошибку.
Я могу, с вашей функцией выше, к этому успешно:
int main() {
unsigned char *B64Encoded;
B64Encoded = (unsigned char *) malloc (1000);
unsigned char *src = "ABC";
Base64Enc(src, 3, B64Encoded);
}
Вам определенно нужно распределить пространство для данных. Вам также нужно выделять больше места, чем src (я думаю, на 1/4 больше).
Строка в кодировке base64 имеет четыре байта на строку данных в трех байтах, поэтому, если srclen равен 300 байтам (или символам), длина строки в кодировке base64 равна 400.
В Википедии есть краткая, но неплохая статья об этом.
Итак, округление srclen до ближайшего кортежа из трех, деленное на три, умноженное на четыре, должно быть достаточно памяти.
Я вижу проблему в вашем коде в том, что он может получить доступ к байту после завершающего нулевого символа, например, если длина строки равна одному символу. Поведение тогда не определено и может привести к исключению, если проверка границы буфера активирована. Р>
Это может объяснить сообщение о доступе к неинициализированной памяти. Р>
Затем вы должны изменить свой код, чтобы обрабатывать конечные символы отдельно. Р>
int len = (scrlen/3)*3;
for( int i = 0; i < len; i += 3 )
{
// your current code here, it is ok with this loop condition.
}
// Handle 0 bits padding if required
if( len != srclen )
{
// add new code here
}
...
PS: вот страница в Википедии, описывающая кодировку Base64 . Р>