Domanda

Ho una domanda per quanto riguarda ordine di allocazione della memoria. Nel seguente codice che allocare in un ciclo 4 stringhe. Ma quando stampo gli indirizzi non sembrano essere assegnato uno dopo l'altro ... Sto facendo qualcosa di sbagliato o è una sorta di meccanismo di difesa attuato dal sistema operativo per prevenire possibili buffer overflow? (Io uso di Windows Vista).

Grazie.

 char **stringArr;
 int size=4, i;

 stringArr=(char**)malloc(size*sizeof(char*));
 for (i=0; i<size; i++)
    stringArr[i]=(char*)malloc(10*sizeof(char));

 strcpy(stringArr[0], "abcdefgh");
 strcpy(stringArr[1], "good-luck");
 strcpy(stringArr[2], "mully");
 strcpy(stringArr[3], "stam");

 for (i=0; i<size; i++) {
  printf("%s\n", stringArr[i]);
  printf("%d  %u\n\n", &(stringArr[i]), stringArr[i]);
 }

Output:

  

abcdefgh   9650064 9650128

     

buona fortuna   9650068 9638624

     

mully   9650072 9638680

     

stam   9650076 9638736

È stato utile?

Soluzione

In genere quando si richiede la memoria attraverso malloc(), la libreria di runtime C arrotonderà le dimensioni della vostra richiesta fino a una certa dimensione minima di allocazione. Questo assicura che:

  • la libreria di runtime ha spazio per le sue informazioni di contabilità
  • è più efficiente per la libreria runtime di gestire blocchi allocati che sono tutti multipli di una certa dimensione (ad esempio 16 byte)

Tuttavia, questi sono dettagli di implementazione e non si può davvero fare affidamento su un particolare comportamento di malloc().

Altri suggerimenti

  

Ma quando stampo gli indirizzi che non sembrano essere assegnati uno dopo l'altro ...

  

Sto facendo qualcosa di sbagliato o è una sorta di meccanismo di difesa attuato dal sistema operativo per prevenire possibili buffer overflow?

Probabilmente "nè".

solo per interesse, quali indirizzi si ottiene?

Non si deve dipendere da un particolare ordinamento o la spaziatura dei valori restituiti da malloc. Si comporta in modi misteriosi e imprevedibili.

In genere è ragionevole aspettarsi che una serie di assegnazioni cronologiche si tradurrà in un'indirizzi di memoria che sono in qualche modo collegati, ma come altri hanno fatto notare, non è certamente un requisito del gestore di heap. In questo caso particolare, però, è possibile che si sta vedendo i risultati della bassa frammentazione heap . Windows tiene gli elenchi dei piccoli blocchi di memoria in grado di soddisfare rapidamente la richiesta. Questi potrebbero essere in qualsiasi ordine.

Non si può dipendere da malloc per darvi indirizzi contigui. E 'interamente alla realizzazione e presumibilmente lo stato attuale del cumulo; alcune implementazioni possono, molti non sarà.

Se è necessario gli indirizzi per essere contigui, allocare un grande blocco di memoria e impostare i puntatori per puntare a diverse aree all'interno di esso.

Come altri hanno già detto, non esiste uno standard per specificare in quale ordine i blocchi di memoria allocata da malloc () dovrebbe essere ubicata nella memoria. Ad esempio, i blocchi liberati possono essere sparsi in tutto il mucchio e possono essere riutilizzate in qualsiasi ordine.

Ma anche se i blocchi capita di essere uno dopo l'altro, molto probabilmente non formano un blocco contiguo. Al fine di ridurre la frammentazione, il gestore di heap solo alloca blocchi di dimensioni specifiche, per esempio potenza di due (64, 128, 256, 512 ecc byte). Quindi, se si riserva 10 byte per una stringa, ci possono essere forse 22 o 54 byte non-usato dopo che.

Il sovraccarico della memoria è un altro motivo per cui non è consigliabile utilizzare allocazione dinamica della memoria a meno che realmente necessario. È molto più facile e più sicuro solo per usare un array statico.

Dal momento che siete interessanti a conoscere gli indirizzi restituiti da malloc(), è necessario assicurarsi che si sta stamparli correttamente. Con il termine "correttamente", voglio dire che si dovrebbe usare il diritto identificatore di formato per printf() per stampare gli indirizzi. Perché stai usando "%u" per uno e "%d" per un altro?

Si dovrebbe usare "%p" per la stampa di puntatori. Questo è anche uno dei rari casi in cui è necessario un cast in C: perché printf() è una funzione variadic, il compilatore non può dire che i puntatori si sta passando come argomento ad esso devono essere del tipo void * o no .

Inoltre, non si deve lanciare il valore di ritorno di malloc().

Dopo aver fissato il sopra, il programma è il seguente:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char **stringArr;
    int size=4, i;

    stringArr = malloc(size * sizeof *stringArr);

    for (i=0; i < size; i++)
        stringArr[i] = malloc(10 * sizeof *stringArr[i]);

    strcpy(stringArr[0], "abcdefgh");
    strcpy(stringArr[1], "good-luck");
    strcpy(stringArr[2], "mully");
    strcpy(stringArr[3], "stam");

    for (i=0; i<size; i++) {
        printf("%s\n", stringArr[i]);
        printf("%p %p\n", (void *)(&stringArr[i]), (void *)(stringArr[i]));
    }
    return 0;
}

e ottengo il seguente output quando l'eseguo:

abcdefgh
0x100100080 0x1001000a0
good-luck
0x100100088 0x1001000b0
mully
0x100100090 0x1001000c0
stam
0x100100098 0x1001000d0

Sul mio computer, puntatori char ** sono lunghi 8 byte, quindi &stringArr[i+1] è a 8 byte superiori &stringArr[i]. Ciò è garantito dalla norma: Se malloc() po 'di spazio, che lo spazio è contiguo. È assegnato spazio per 4 puntatori, e gli indirizzi di quei quattro puntatori sono uno accanto all'altro. Si può vedere che più chiaramente facendo:

printf("%d\n", (int)(&stringArr[1] - &stringArr[0]));

Questo dovrebbe stampare 1.

Sulle malloc()s successive, poiché ogni stringArr[i] è ottenuto da un malloc() separato, l'implementazione è libero di assegnare alcuni indirizzi adatti a loro. Sul mio implementazione, con quel particolare periodo, gli indirizzi sono tutti 0x10 byte a parte.

Per la vostra applicazione, sembra che i puntatori char ** sono lunghi 4 byte.

A proposito di indirizzi del vostro singola stringa, lo fa apparire come malloc() sta facendo una sorta di randomizzazione (che si è permesso di fare).

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