2012-09-13 1 views
5

perché non si sta dando errore durante la compilazione?Perché non ottengo un errore di segmentazione quando scrivo oltre la fine di un array?

#include <iostream> 
using namespace std; 

int main() 
{ 
    int *a = new int[2]; 
    // int a[2]; // even this is not giving error 
    a[0] = 0; 
    a[1] = 1; 
    a[2] = 2; 
    a[3] = 3; 
    a[100] = 4; 
    int b; 

    return 0; 
} 

qualcuno può spiegare perché questo sta accadendo. Grazie in anticipo.)

+4

Sfortunatamente, il comportamento definito ** a volte ** è un sottoinsieme di comportamento non definito :( – Mahesh

+0

@Mahesh :)) no. –

+1

@LuchianGrigore ** A volte ** – Mahesh

risposta

2

Suppongo che tu venga da Java o da un linguaggio simile a Java dove, una volta uscito dal limite di un array, ottieni l'eccezione "indice di array fuori limite".

Bene, C si aspetta di più da te; salva lo spazio che chiedi, ma non controlla se stai andando fuori dal limite di quello spazio salvato. Una volta fatto ciò come sopra menzionato, il programma ha quel comportamento indefinito temuto.

E ricorda per il futuro che se hai un bug nel tuo programma e non riesci a trovarlo, e quando vai sul codice/esegui il debug, tutto sembra OK, c'è una buona possibilità che tu sia " ri "fuori dai limiti" e accedere a un luogo non assegnato.

9

Perché un comportamento indefinito == tutto può succedere. Sei sfortunato che non si blocca, questo tipo di comportamento può potenzialmente nascondere bug.

Come per a essere definito due volte - questo è un bug nel compilatore.

+0

Mi dispiace. "a" non è stato dichiarato due volte. Volevo solo dire che entrambe le dichiarazioni si stanno comportando allo stesso modo. – singingsingh

+0

@singingsingh ok :) quindi ignorare il secondo paragrafo. –

8

La dichiarazione di due variabili chiamate a rappresenta sicuramente un errore; se il tuo compilatore lo accetta, allora è rotto. Immagino tu intenda che non ricevi ancora un errore se sostituisci una dichiarazione con l'altra.

L'accesso alla matrice non è controllato. Al momento della compilazione, la dimensione di un array spesso non è nota e la lingua non richiede un controllo anche quando lo è. In fase di esecuzione, un controllo ridurrebbe le prestazioni, il che andrebbe contro la filosofia C++ di non pagare per qualcosa che non è necessario. Quindi l'accesso oltre la fine di un array dà un comportamento indefinito, ed è compito del programmatore assicurarsi che non accada.

A volte, un accesso non valido causa un errore di segmentazione, ma questo non è garantito. In genere, la protezione della memoria viene applicata solo a intere pagine di memoria, con una dimensione di pagina tipica di alcuni kilobyte. Nessun accesso all'interno di una pagina di memoria valida non verrà catturato. C'è una buona probabilità che la memoria a cui accedi contenga qualche altra variabile del programma, o parte dello stack delle chiamate, quindi scrivere lì potrebbe influenzare il comportamento del programma praticamente in qualsiasi modo tu possa immaginare.

Se si desidera essere sicuri, è possibile utilizzare std::vector e accedere solo ai suoi elementi utilizzando la sua funzione at(). Questo controllerà l'indice e genererà un'eccezione se è fuori portata. Gestirà anche l'allocazione della memoria per te, riparando la perdita di memoria nell'esempio.

+0

Mi dispiace. "a" non è stato dichiarato due volte. Volevo solo dire che entrambe le dichiarazioni si stanno comportando allo stesso modo. – singingsingh

0

I compilatori con una buona analisi del codice avviserebbero sicuramente su quel codice che fa riferimento oltre l'allocazione dell'array. dimenticando il multiplo di una dichiarazione, se lo si esegue, può o non può essere criticato (comportamento non definito come altri hanno detto). se, ad esempio, hai una pagina 4KB di heap (nello spazio degli indirizzi del processore), se non scrivi all'esterno di quella pagina, non riceverai un errore dal processore. dopo l'eliminazione dell'array, se l'avessi fatto, e in base all'implementazione dell'heap, l'heap potrebbe rilevare che è corrotto.