Domanda

Va ??bene, questo mi ha sconcertato per un po '.

la seguente funzione codifica una stringa in 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;
}

Ora, sulla funzione che chiama Base64Enc () ho:

unsigned char *B64Encoded;

Qual è l'argomento che passo su char * dest senza segno nella funzione di codifica base 64. Ho provato diverse inizializzazioni da malloc a NULL ad altre inizializzazioni. Indipendentemente da ciò che faccio, ottengo sempre un'eccezione e se non lo inizializzo, il compilatore (compilatore VS2005 C) genera un avviso che mi informa che non è stato inizializzato. Se eseguo questo codice con la variabile non inizializzata a volte funziona e altri no. Come posso inizializzare quel puntatore e passarlo alla funzione?

È stato utile?

Soluzione

è necessario allocare buffer sufficientemente grande da contenere il risultato codificato. O allocarlo nello stack, in questo modo:

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

Ma è facile causare un overflow del buffer dello stack allocando troppo poco spazio usando questo approccio. Sarebbe molto meglio se lo allocassi nella memoria dinamica:

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

Non dimenticare di liberare () il buffer allocato dopo aver finito.

Altri suggerimenti

Sembra che tu voglia usare qualcosa del genere:

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

Sarebbe utile se tu fornissi l'errore.

Posso, con la tua funzione sopra, farlo con successo:

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

}

sicuramente devi distribuire spazio per i dati. Devi anche distribuire più spazio di src (1/4 in più credo).

Una stringa codificata in base64 ha quattro byte per tre byte nella stringa di dati, quindi se srclen è 300 byte (o caratteri), la lunghezza della stringa codificata in base64 è 400.

Wikipedia ha un breve ma abbastanza buono articolo su di esso.

Quindi, arrotondando srclen alla tupla più vicina di tre, divisa per tre, quattro volte dovrebbe essere esattamente abbastanza memoria.

Vedo un problema nel tuo codice nel fatto che potrebbe accedere al byte dopo il carattere null finale, ad esempio se la lunghezza della stringa è un carattere. Il comportamento non è quindi definito e può comportare un'eccezione se il controllo del limite del buffer è attivato.

Questo può spiegare il messaggio relativo all'accesso alla memoria non inizializzata.

Dovresti quindi modificare il codice in modo da gestire i caratteri finali separatamente.

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: ecco una pagina di Wikipedia che descrive codifica Base64 .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top