2015-09-30 22 views
11

programmaallocazione della memoria per il programma C

#include<stdio.h> 
int a=10; 
void main() 
{ 
    int i=0; 
    printf("global = %p, local = %p\n",&a,&i); 
    main(); 
} 

uscita

[email protected]:~/Advanced_Unix/Chapter7$ ./a.out 
global = 0x804a014, local = 0xbfff983c 
global = 0x804a014, local = 0xbfff980c 
. 
. 
. 
global = 0x804a014, local = 0xbf7fac9c 
global = 0x804a014, local = 0xbf7fac6c 
global = 0x804a014, local = 0xbf7fac3c 
Segmentation fault (core dumped) 
[email protected]:~/Advanced_Unix/Chapter7$ 

Il programma sopra ottiene errore di segmentazione. Perché, il principale si chiama in modo ricorsivo. Quanto segue è l'assegnazione della memoria ad un programma C.

allocazione di memoria

  __________________      __________________ 
      |    |      |    | 
      |  stack  |      |  Main  | 
      | ↓    |      |----------------| 
      ------------------      |  Main  | 
      |    |      |----------------| 
      | <Un Allocated|      |  Main  | 
      |  space> |      |----------------| 
      ------------------      |  Main  | 
      |    |      |----------------| 
      | ↑   |      |  Main  | 
      |  Heap  |      |----------------| 
      |    |      |  Main  | 
      |    |      |----------------| 
      __________________      |////////////////| ---> Collision occurs. So, Segmentation fault Occurs. 
      |    |      |________________| 
      |  data  |      |  data  | 
      __________________      |________________| 
      |  text  |      |  text  | 
      __________________      |________________| 
       Figure(a)        Figure(b) 

Quindi, mi aspetto che viene mostrato come in figura (b), la chiamata principale in modo ricorsivo. Se raggiunge il segmento di dati, si verifica la collisione. Se si verifica, non c'è più spazio da allocare per la funzione principale. Quindi, ottiene errore di errore di segmentazione. Quindi, usando il programma di cui sopra, lo sperimento. Su quel programma, l'indirizzo della variabile globale 'a' è "0x804a014". Ogni volta che viene chiamato main, viene dichiarata la variabile locale "i". Quindi, I si aspetta, prima dell'errore di segmentazione, l'indirizzo di i è quasi l'indirizzo di 'a'. Ma entrambi gli indirizzi sono molto diversi. Quindi, cosa sta succedendo qui?

Perché l'indirizzo di 'a' e 'i' non è nello stesso intervallo al momento dell'errore di errore di segmentazione. Quindi, come verificare se il main raggiunge la dimensione dello stack e viene sovraccaricato?

+5

mette in pausa il programma e dà un'occhiata a/proc/pid/maps - ci sono altre cose, come le librerie. Inoltre, esiste un limite effettivo alle dimensioni dello stack (ulimit) – Petesh

+0

È possibile stampare gli indirizzi degli oggetti dalle librerie? Dì, & stdin? O stdin? –

+0

@Petesh Questa è la dimensione dello stack: bf99c000-bfa39000 rw-p 00000000 00:00 0 [stack] – mrg

risposta

0

'a' è una variabile globale e non sarà in pila. Questo sarà nella sezione dati - ad esempio, bss inizializzato

"i" è una variabile locale e verrà memorizzato nello stack.

Queste sono sezioni completamente diverse e quindi la differenza.

Fare riferimento Global memory management in C++ in stack or heap?

0

Quando hai scritto variabile "i" ottiene dichiarato, si sta scrivendo qualcosa di corretto, ma la variabile non è dichiarata come globale a.

i è stack allocato e stack ha le proprie dimensioni.

ulimit può modificare tale limite.

Quello che si sta cercando di vedere, collisione tra l'allocazione degli indirizzi di una variabile globale e una variabile locale, non è possibile.

1

Lo schema è un modello concettuale o una possibile implementazione. Ad esempio, un programma con multithreading avrà uno stack per thread e un singolo heap, che non si adatta perfettamente allo schema semplificato.

Tutto ciò che è richiesto è che il sistema consenta la ricorsione, nel senso che ogni nuova chiamata di una funzione ottiene una copia privata delle variabili locali. Tutto ciò che rimane dipende dall'implementazione.

recente assegnazione pagina uso del sistema, e di un processo ottiene generalmente un insieme di segmenti di pagina, ma non sono necessariamente consecutivi, e si può avere fori tra loro dove qualsiasi accesso otterrà un SIGSEGV (violazione segmento)

TL/DR: il tuo programma avrà probabilmente un segnale SIGSEGV dell'indirizzo della variabile dinamica che raggiunge l'indirizzo di quello statico - dovresti trovare una vecchia casella MS/DOS per mostrare questo comportamento ...

0

il modello di memoria che hai è un'enorme semplificazione che è utile solo per iniziare a insegnare le basi della memoria agli studenti per non travolgerli con deta è all'inizio. Proprio come iniziamo l'educazione matematica con l'aggiunta di numeri naturali. È un buon fondamento ma non ti porterà lontano se usi proprio questo per capire la realtà.

Questo modello non è stato accurato per almeno 25-30 anni e non può essere utilizzato per fare previsioni sul comportamento effettivo del programma. Possono esserci dozzine, se non migliaia, di altri mapping di memoria tra l'heap e lo stack (librerie condivise, mallocs di grandi dimensioni, mmap di file, ecc.). Il concetto di "heap" è altamente problematico perché spesso non è molto più della somma di tutte le allocazioni dinamiche della memoria anonima in qualsiasi punto dello spazio degli indirizzi per scopi che il sistema operativo non conosceva in anticipo.

Quello che sta accadendo nell'esempio è che si esegue il limite di risorse dello stack (vedere ulimit -s).