Perché il compilatore non si lamenta quando provo ad accedere a un valore di array inesistente?

1

Il mio libro C ++ dice che se ho

int anArray[25];

e provo a valutare

anArray[25] = 0;

il programma semplicemente sovrascrive qualunque valore sia memorizzato nel prossimo indirizzo di memoria oltre la fine dell'array. Perché?

Il mio pensiero è che i compilatori sono stupidi al riguardo. Tutto quello che il compilatore si preoccupa di fare è calcolare dove un array [25] dovrebbe essere e poi andare avanti.

    
posta moonman239 12.04.2016 - 02:28
fonte

2 risposte

8

Perché il compilatore non si lamenta? Perché non è richiesto. Lo standard di linguaggio descrive le circostanze che richiedono un compilatore di lamentarsi, e un semplice array-index-out-of-bounds non è uno di questi.

Gli strumenti di analisi statica decenti sono in grado di rilevare questo scenario per casi specifici. Il semplice caso di:

int anArray[25];
anArray[25] = 0;

verrà probabilmente rilevato dalla maggior parte degli strumenti di analisi statici. Ma i compilatori C e C ++ non sono tenuti a farlo.

Per quanto riguarda il motivo per cui lo standard non li richiede ... perché dovrebbe?

Il tuo scenario particolare è solo banalmente rilevabile per due motivi:

  1. Il compilatore conosce le dimensioni di quell'array.

  2. L'indice che stai usando è conosciuto dal compilatore in fase di compilazione.

Nei casi reali di scenari indicizzati fuori limite, uno o entrambi questi di solito non sono veri. E no, C ++ in realtà non ha modo di sapere cosa la lunghezza di un array è . Perché puoi fare questo:

int *arr = new int[25];
int *arr2 = arr + 5;

arr2 è tanto una matrice quanto arr . Eppure, non c'è modo di determinare quanti elementi sono in arr2 .

E anche se tu potessi ... non sarebbe qualcosa che sapresti in tempo di compilazione . Accedere a tale lunghezza sarebbe un accesso alla memoria di runtime. Una volta che l'array diventa int* , non è più un array; è solo un puntatore, a cui puoi accedere come se fosse un array. Il compilatore non ha più una certa conoscenza di ciò che viene memorizzato lì. Quindi hai perso # 1.

Quindi non c'è modo che il compilatore possa lamentarsi nella maggior parte dei casi reali che sono problematici.

La prossima domanda, non richiesta, è perché il compilatore non emette il codice runtime per verificare cose come questa? Perché tale runtime richiede tempo e, per impostazione predefinita, C e C ++ sono lingue non sicure . In base alla progettazione, sono intesi per ottenere le prestazioni più veloci possibili, anche se ciò significa che la scrittura di codice spezzato (o fragile) è più semplice rispetto alla scrittura del codice corretto.

Puoi piacere o odiarlo, applaudirlo o deriderlo. Comunque ti senti, questa è l'etica del design delle lingue.

    
risposta data 12.04.2016 - 04:35
fonte
0

Il MIT (credo) ha archiviato alcuni fantastici corsi online che stavo osservando. Una delle cose davvero interessanti e potenti su come essere in grado di fare questo è che puoi accedere specificamente alla memoria che normalmente non ti è permesso. Questo ti offre tutti i modi per fare cose che probabilmente non dovresti. ;)

Ma penso che il motivo principale per cui ciò sia possibile è che una variabile di matrice in realtà memorizza solo l'indirizzo del primo indice . Non ho un modo, che io sappia, di archiviare in modo specifico quanto sia grande l'array. Ovviamente, da qualche parte in memoria questa informazione è esistita ad un certo punto perché una quantità appropriata di memoria è stata messa da parte per l'array di una certa dimensione, ma per qualsiasi motivo questo non è facilmente recuperabile.

    
risposta data 12.04.2016 - 03:52
fonte

Leggi altre domande sui tag