RISOLTO Problemi con allocazione dinamica della memoria

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
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:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
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).
 

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
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
 

rodhellas

Utente Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit
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).
 

Matteo34

Nuovo Utente
104
3
CPU
i5-10500 3.2Ghz
Dissipatore
Non specificato
Scheda Madre
Non specificata
HDD
M.2 251GB e M.2 500GB
RAM
16GB DDR4 2666mhz
GPU
Grafica Intel® UHD 630
Audio
Non specificata
Monitor
1920x1080 27"
PSU
Non specificato
Case
Non specificato
Periferiche
Nono specificato
Net
Eolo
OS
Ubuntu
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ù
 

Andretti60

Utente Èlite
6,440
5,091
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.
 

pabloski

Utente Èlite
2,868
916
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:
  • Mi piace
Reazioni: Andretti60

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili