Pregunta

Muy bien, este me ha estado desconcertando por un momento.

la siguiente función codifica una cadena en la base 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;
}

Ahora, en la función que llama a Base64Enc () tengo:

unsigned char *B64Encoded;

¿Cuál es el argumento que paso a unsign char * dest en la función de codificación base 64? He intentado diferentes inicializaciones de mallocs a NULL a otras inicializaciones. No importa lo que haga, siempre obtengo una excepción y si no lo inicializo, el compilador (compilador VS2005 C) emite una advertencia que me dice que no se ha inicializado. Si ejecuto este código con la variable no inicializada, algunas veces funciona y otras no. ¿Cómo inicializo ese puntero y lo paso a la función?

¿Fue útil?

Solución

necesita asignar un búfer lo suficientemente grande como para contener el resultado codificado. Puede asignarlo en la pila, de esta manera:

unsigned char B64Encoded[256]; // the number here needs to be big enough to hold all possible variations of the argument

Pero es fácil provocar un desbordamiento del búfer en la pila al asignar muy poco espacio con este enfoque. Sería mucho mejor si lo asigna en la memoria dinámica:

int cbEncodedSize = srclen * 4 / 3 + 1;  // cbEncodedSize is calculated from the length of the source string
unsigned char *B64Encoded = (unsigned char*)malloc(cbEncodedSize);

No olvides liberar () el búfer asignado después de que hayas terminado.

Otros consejos

Parece que le gustaría usar algo como esto:

// 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);

Sería útil si proporcionaras el error.

Puedo, con su función anterior, hacer esto con éxito:

int main() {
    unsigned char *B64Encoded;
    B64Encoded = (unsigned char *) malloc (1000);
    unsigned char *src = "ABC";
    Base64Enc(src, 3, B64Encoded);

}

Usted definitivamente necesita malloc espacio para los datos. También necesita malloc más espacio que src (1/4 más, creo).

Una cadena codificada en base64 tiene cuatro bytes por cadena de datos de tres bytes, por lo que si srclen es 300 bytes (o caracteres), la longitud de la cadena codificada en base64 es 400.

Wikipedia tiene un breve pero bastante bueno artículo al respecto.

Entonces, redondeando srclen a la tupla más cercana de tres, dividido por tres, multiplicado por cuatro debería ser exactamente suficiente memoria.

Veo un problema en su código en el hecho de que puede acceder al byte después del carácter nulo final, por ejemplo, si la longitud de la cadena es un carácter. El comportamiento no está definido y puede generar una excepción si se activa la comprobación de límites de búfer.

Esto puede explicar el mensaje relacionado con el acceso a la memoria no inicializada.

A continuación, debe cambiar su código para manejar los caracteres finales por separado.

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
}

...

PD: Aquí hay una página de Wikipedia que describe codificación Base64 .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top