RISOLTO Problemi con allocazione dinamica della memoria

Pubblicità

Matteo34

Nuovo Utente
Messaggi
104
Reazioni
3
Punteggio
45
Intanto ciao a tutti, ho un problema con un programma in C, più che un problema è un mancato errore da parte del compilatore.
Vado ad allocare dinamicamente 12 byte in memoria, ma non so per quale motivo se provo ad accedere a un indirizzo, in teoria inaccessibile, mi fa scrivere al suo interno.

CODICE:

Codice:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    int *ptr;
    ptr = malloc(3*sizeof(int));
    scanf("%d", (ptr + 56));
    return 0;
}

Come si vede provo ad accedere a una locazione a me non accessibile, visto che sto provando ad accedere a un indirizzo che si trova a 224 byte in avanti rispetto al primo elemento dell'array.
Il problema e che non ricevo nessun tipo di errore, mi fa scrivere in quel indirizzo e poi il programma termina, neanche un errore di overflow, niente di NIENTE.
Vorrei capire perchè?
 
Ultima modifica:
Ciò che alloca malloc non è quella dimensione esatta, dipende dalla granularità. Viene comunque allocato un chunk di memoria più ampio di quello. La dimensione dipende dall'OS, così come dall'hw e dall'implementazione della lib (malloc in questo caso).
 
Ciò che alloca malloc non è quella dimensione esatta, dipende dalla granularità. Viene comunque allocato un chunk di memoria più ampio di quello. La dimensione dipende dall'OS, così come dall'hw e dall'implementazione della lib (malloc in questo caso).
Si ok, ma mi sembrano un po' esagerati 224 byte in più rispetto ai 12byte che doveva allocare standard
 
E' uno dei undefined behaviour di C. Devi sempre assicurarti che quando fai operazioni sui puntatori, il range delle operazioni sia sempre dentro alla zona allocata dalla malloc. Se non lo fai può funzionare come no. (se metti 56000 invece che 56 ti dà segfault, coerente con quanto detto dal buon Dispatch).
 
E' uno dei undefined behaviour di C. Devi sempre assicurarti che quando fai operazioni sui puntatori, il range delle operazioni sia sempre dentro alla zona allocata dalla malloc. Se non lo fai può funzionare come no. (se metti 56000 invece che 56 ti dà segfault, coerente con quanto detto dal buon Dispatch).
Ma per quale motivo mi fa scrivere in una zona di memoria che non ho allocato con la malloc, anche se viene allocata un po' più di memoria mi sembrano esagerati di 224byte in più
 
Ciao Matteo e buon Natale

1) il compilatore C non fa nessun controllo sulla allocazione della memoria per molti motivi, per lo più storici. Principalmente perché ci dà la possibilità di scrivere/leggere ovunque vogliamo. Il che è utile, ma se non sappiamo quello che stiamo facendo causa problemi
2) lo standard C definisce “cosa” fanno le funzioni, ma non “come” siano implementate. Ci sono dozzine di librerie che implementano malloc() in modi diversi, che funzionano più o meno bene a seconda della situazione. Ma i dettagli non sono sempre noti, e infatti non dovrebbero essere noti. In pratica quasi tutte le implementazioni allocano memoria in multipli della “page size” del sistema, tipicamente 4K, che è ben più di quel tuo offset di 224 byte (prova un offset superiore a 4K e vedi che succede). Comunque non è sempre detto che accedere a una zona di memoria non allocata dia errore (segmentation fault), succede se si va fuori dalla zona accessibile al programma, e in genere il risultato non è definito. Quello che si causa viene chiamato “memory corruption “, che magari non causa problemi immediati ma in seguito quando quella memoria viene letta e non è nel formato giusto. E sono grossi grattacapi.
 
Ma per quale motivo mi fa scrivere in una zona di memoria che non ho allocato con la malloc, anche se viene allocata un po' più di memoria mi sembrano esagerati di 224byte in più

Pagine pagine. L'unità di allocazione fondamentale è la pagina, che è 4KB. I parametri d'accesso si possono settare per pagina. Puoi stabilire che la pagina X è read-write, ma non puoi dire che 300 bytes di quella pagina sono read-write e il resto è read-only.

Quando usi linguaggi come Java, noti che non ti consente di andare oltre il buffer allocato. Ma questo perchè i controlli li fa il linguaggio. E C non implementa nessun controllo sugli accessi in memoria. Se tenti di scrivere in una pagina read-only, è il processore a generare un fault e mandare tutto all'aria. C se ne frega bellamente.

Esempio https://linux.die.net/man/2/mprotect

mprotect() changes protection for the calling process's memory page(s) containing any part of the address range in the interval [addr, addr+len-1]. addr must be aligned to a page boundary.

Come vedi non se ne esce. La CPU ragiona per pagine, non per blocchi di memoria di dimensioni definite dal programmatore.
 
Ultima modifica:
Pubblicità
Pubblicità
Indietro
Top