Инициализация указателя? для конкретной функции

StackOverflow https://stackoverflow.com/questions/1041072

Вопрос

Хорошо, это меня немного озадачило.

следующая функция кодирует строку в базу 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 .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top