Domanda

Ho questo pezzo di codice

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

int main(){
    void *a, *b;

    a = malloc(16);
    b = malloc(16);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);

    a = malloc(1024);
    b = malloc(1024);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);  
}

Non dovrebbe stampare l'ultima dimensione del blocco allocata (16 o 1024)? Stampa invece 24 e 1032, quindi la quantità di memoria allocata sembra avere 8 byte extra.

Il mio problema è (prima di creare questo caso di test) che eseguo malloc() in una funzione (1024 byte) e restituisco il risultato assegnato. Quando controllo la dimensione del blocco sul ritorno della funzione ottengo 516 blocchi ... e non capisco il perché. Immagino che questo potrebbe essere il motivo del danneggiamento della memoria che si verifica dopo aver eseguito un po 'di elaborazione sui buffer allocati :)

Modifica: ho visto Come posso ottenere la dimensione di un array da un puntatore in C? e sembra chiedere la stessa cosa, scusate il ripubblicare.

Ho rifatto il mio esempio con il mio codice più specifico:

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

short int * mallocStuff(long int number, short int base){
    short int *array;
    int size=1024;

    array=(short int*)calloc(1,size);
    //array=(short int*)malloc(size);

    return array;
}

int main(){
    short int **translatedArray;

    translatedArray=malloc(4*sizeof(short int));

    int i;
    for(i=0;i<4;i++){
        translatedArray[i]=mallocStuff(0,0);

        if(i>0)
            printf("\n   block size (for a): %p-%p : %i",
                translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
    }

    return 0;
}

E l'output è

   block size (for a): 0x804a420-0x804a018 : 516
   block size (for a): 0x804a828-0x804a420 : 516
   block size (for a): 0x804ac30-0x804a828 : 516

Secondo il precedente post che è più grande di 1024. Sbaglio?

È stato utile?

Soluzione

Hai un bug. Invece di:

translatedArray=malloc(4*sizeof(short int));

Dovresti avere

translatedArray=malloc(4*sizeof(short int*));

Nota il puntatore mancante nel tuo codice. Ho il sospetto che da qui derivi il tuo comportamento osservato.


Nota anche che 0x804a420 - 0x804a018 = 1032, non 516. La formula translatedArray[i] - translatedArray[i - 1] ti dà il numero di elementi (short short o, più semplicemente, short) tra i due indirizzi, non il numero di byte .

Altri suggerimenti

In primo luogo, Malloc non garantisce che due chiamate malloc successive restituiscano puntatori successivi.

In secondo luogo, a seconda dell'architettura specifica, si applicano regole di allineamento diverse; a volte potresti chiedere un singolo byte, ma l'architettura preferisce le allocazioni su intervalli di 8 o 4 byte.

In terzo luogo, malloc ha bisogno di un certo overhead per memorizzare la dimensione del blocco allocato, ecc.

Non fare ipotesi su cosa sta facendo malloc oltre a ciò che dice la documentazione!

La funzione malloc alloca sempre leggermente più di quanto richiesto, al fine di memorizzare alcune informazioni contabili. Dopotutto, quando chiami free() devi sapere quanto è grande il blocco.

Inoltre, generalmente short int le implementazioni arrotondano la dimensione richiesta fino al multiplo successivo di 8 o 16 o qualche altro numero arrotondato.

Aggiorna : la vera risposta alla tua domanda risiede nel tuo uso del tipo <=>. Quando si esegue l'aritmetica del puntatore (sottrazione) tra i puntatori digitati, C e C ++ restituiscono la differenza nel numero delle cose indicate. Dato che stai puntando a <=>, che ha una dimensione di due byte, il valore restituito è la metà di quello che ti aspetti.

D'altra parte, <=> alloca sempre un dato numero di byte , indipendentemente da ciò a cui in seguito hai lanciato il risultato. Prova questo:

    array=(short int*)malloc(sizeof(short int) * size);

Non ci sono garanzie che due chiamate malloc restituiscano blocchi esattamente impacchettati insieme - in realtà non ci sono garanzie sul risultato, tranne che se non è NULL indicherà un blocco grande almeno quanto quello richiesto.

Internamente, la maggior parte dei malloc contiene dati di lavoro per aiutarli a gestire l'heap. Ad esempio, quegli 8 byte potrebbero contenere due puntatori: uno che punta al blocco successivo e uno che punta al blocco precedente. Non so cosa siano quegli 8 byte perché non hai menzionato il sistema operativo su cui stai eseguendo, ma è perfettamente normale che malloc usi un po 'di memoria per sé dietro le quinte.

Alcuni allocatori (ad esempio su Windows) forniscono una funzione di libreria per scoprire la dimensione del blocco con un puntatore, tuttavia altri no, poiché è una caratteristica piuttosto esoterica.

Ciò che restituisce malloc dipende dall'implementazione di malloc e dall'architettura. Come altri hanno già detto, sei sicuro di ottenere almeno la quantità di memoria richiesta o NULL. Questo è anche il motivo per cui a volte è possibile scrivere oltre la fine di un array e non ottenere un errore di segmentazione. È perché in realtà hai un valido accesso a questa memoria, semplicemente non lo sapevi.

malloc () viene solitamente implementato suddividendo l'heap disponibile in blocchi di varie dimensioni. Nel tuo caso, malloc () restituisce 2 blocchi consecutivi di 1024 (o 16) byte. Lo spazio di 8 byte menzionato viene utilizzato da malloc () per le informazioni di contabilità.

Vedi le note impl di malloc () di Doug Lea qui per capire cosa sta succedendo dietro le quinte: http://g.oswego.edu/dl/html/malloc.html |

malloc() avrà il proprio overhead.

Per non parlare del fatto che non vi è alcuna garanzia che 2 allocazioni consecutive saranno una accanto all'altra per cominciare.

Se malloc restituisce qualcosa di diverso da null, la memoria che è stata allocata per il tuo programma ha le dimensioni che hai passato a <=>. Portare la differenza del puntatore tra i valori di ritorno di due chiamate di differenza su <=> potrebbe avere qualsiasi valore e non ha nulla (ben poco) a che fare con la dimensione del blocco del primo blocco allocato.

Ho trovato questo ... e controlla il link qui sotto per maggiori informazioni.

Allocazione

Un blocco viene allocato dal pool libero convertendo prima i byte richiesti in un indice nell'array bucket, utilizzando la seguente equazione:

necessario = richiesto + 8

Se necessario < = 16, poi bucket = 0

Se necessario > 16, poi bucket = (log (necessario) / log (2) arrotondato per difetto all'intero più vicino) - 3

La dimensione di ciascun blocco nell'elenco ancorato dal bucket è dimensione del blocco = 2 bucket + 4. Se l'elenco nel bucket è nullo, la memoria viene allocata utilizzando la subroutine sbrk per aggiungere blocchi all'elenco. Se la dimensione del blocco è inferiore a una pagina, una pagina viene allocata utilizzando la subroutine sbrk e il numero di blocchi raggiunti dividendo la dimensione del blocco in dimensione della pagina viene aggiunto all'elenco. Se la dimensione del blocco è uguale o maggiore di una pagina, la memoria necessaria viene allocata utilizzando la subroutine sbrk e un singolo blocco viene aggiunto all'elenco libero per il bucket. Se l'elenco libero non è vuoto, il blocco in testa all'elenco viene restituito al chiamante. Il blocco successivo nell'elenco diventa quindi il nuovo head.

http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

Prima che il puntatore abbia le dimensioni della seguente matrice, che è un numero intero a 32/64 bit (non so se firmato o non firmato)

quindi la quantità di memoria allocata sembra avere 8 byte extra? malloc() l'implementazione sul tuo sistema sembra allocare byte extra per mantenere informazioni sui metadati come quanto è grande la sezione heap, qual è indirizzo di partenza ecc. informazioni.

Anche se varia su piattaforme diverse. Sui miei sistemi X86, 17 allocando min di malloc(0) byte, anche se sto richiedendo <=>.

int main(void) {
    int *p = malloc(0);
    if(p == NULL) {
        /* error handling */
    }
    printf("%d\n",p[-1]);/ *it prints 17 bytes */
    /* some code */
    return 0;
}

malloc () può allocare memoria contigua, ma quando chiami malloc () 2 volte e non puoi aspettarti che la memoria allocata sia contigua sottraendo due puntatori variabls ...

Comunque la memoria allocata è la memoria virtuale che fa parte dell'implementazione del kernel, la gestione della memoria (VFS) deve essere specifica. Potrebbe non influire sulla funzionalità dell'applicazione.

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