c errors undefined reference
differenza tra controllo di qualità e garanzia
Questo tutorial descrive gli errori critici che i programmatori incontrano spesso in C ++ come riferimento non definito, un errore di segmentazione (core dump) e un simbolo esterno non risolto:
Discuteremo gli errori più importanti che spesso incontriamo in C ++ che sono davvero altrettanto critici. Oltre agli errori di sistema e semantici e alle eccezioni che si verificano di volta in volta, otteniamo anche altri errori critici che influenzano l'esecuzione dei programmi.
Questi errori si verificano principalmente verso la fine del programma in fase di esecuzione. A volte il programma fornisce un output corretto e quindi si verifica l'errore.
=> Visita qui per imparare C ++ da zero.
Cosa imparerai:
Importanti errori C ++
In questo tutorial, discuteremo tre tipi di errori che sono critici dal punto di vista di qualsiasi programmatore C ++.
- Riferimento indefinito
- Errore di segmentazione (core dump)
- Simbolo esterno non risolto
Discuteremo le possibili cause di ciascuno di questi errori e insieme alle precauzioni che possiamo prendere come programmatore per prevenire questi errori.
Iniziamo!!
Riferimento indefinito
Un errore 'Riferimento non definito' si verifica quando abbiamo un riferimento al nome dell'oggetto (classe, funzione, variabile, ecc.) Nel nostro programma e il linker non riesce a trovare la sua definizione quando cerca di cercarlo in tutti i file e le librerie di oggetti collegati .
Pertanto, quando il linker non riesce a trovare la definizione di un oggetto collegato, emette un errore di 'riferimento non definito'. Come risulta dalla definizione, questo errore si verifica nelle fasi successive del processo di collegamento. Ci sono vari motivi che causano un errore di 'riferimento non definito'.
Discutiamo alcuni di questi motivi di seguito:
# 1) Nessuna definizione fornita per l'oggetto
Questo è il motivo più semplice per causare un errore di 'riferimento non definito'. Il programmatore ha semplicemente dimenticato di definire l'oggetto.
Considera il seguente programma C ++. Qui abbiamo solo specificato il prototipo della funzione e poi lo abbiamo utilizzato nella funzione principale.
#include int func1(); int main() { func1(); }
Produzione:
Quindi, quando compiliamo questo programma, viene emesso l'errore del linker che dice 'riferimento non definito a' func1 () ''.
Per eliminare questo errore, correggiamo il programma come segue fornendo la definizione della funzione func1. Ora il programma fornisce l'output appropriato.
#include using namespace std; int func1(); int main() { func1(); } int func1(){ cout<<'hello, world!!'; }
Produzione:
Ciao mondo!!
# 2) Definizione errata (le firme non corrispondono) degli oggetti utilizzati
Un'altra causa di errore di 'riferimento non definito' è quando specifichiamo definizioni sbagliate. Usiamo qualsiasi oggetto nel nostro programma e la sua definizione è qualcosa di diverso.
Considera il seguente programma C ++. Qui abbiamo effettuato una chiamata a func1 (). Il suo prototipo è int func1 (). Ma la sua definizione non corrisponde al suo prototipo. Come si vede, la definizione della funzione contiene un parametro alla funzione.
Pertanto, quando il programma viene compilato, la compilazione ha esito positivo a causa della corrispondenza tra prototipo e chiamata di funzione. Ma quando il linker cerca di collegare la chiamata alla funzione con la sua definizione, trova il problema e genera l'errore come 'riferimento non definito'.
#include using namespace std; int func1(); int main() { func1(); } int func1(int n){ cout<<'hello, world!!'; }
Produzione:
Pertanto, per prevenire tali errori, controlliamo semplicemente se le definizioni e l'utilizzo di tutti gli oggetti corrispondono nel nostro programma.
# 3) File oggetto non collegati correttamente
Questo problema può anche dare origine all'errore 'riferimento non definito'. Qui, potremmo avere più di un file sorgente e potremmo compilarli indipendentemente. Al termine, gli oggetti non sono collegati correttamente e si ottiene un 'riferimento indefinito'.
Considera i seguenti due programmi C ++. Nel primo file, utilizziamo la funzione 'print ()' definita nel secondo file. Quando compiliamo questi file separatamente, il primo file fornisce un 'riferimento non definito' per la funzione di stampa, mentre il secondo file fornisce 'riferimento non definito' per la funzione principale.
int print(); int main() { print(); }
Produzione:
int print() { return 42; }
Produzione:
Il modo per risolvere questo errore è compilare entrambi i file contemporaneamente ( Per esempio, utilizzando g ++).
Oltre alle cause già discusse, può verificarsi anche un 'riferimento indefinito' per i seguenti motivi.
# 4) Tipo di progetto sbagliato
Quando specifichiamo tipi di progetto errati negli IDE C ++ come lo studio visivo e proviamo a fare cose che il progetto non si aspetta, otteniamo un 'riferimento indefinito'.
# 5) Nessuna libreria
Se un programmatore non ha specificato correttamente il percorso della libreria o si è completamente dimenticato di specificarlo, allora otteniamo un 'riferimento non definito' per tutti i riferimenti che il programma utilizza dalla libreria.
# 6) I file dipendenti non vengono compilati
Un programmatore deve assicurarsi di compilare in anticipo tutte le dipendenze del progetto in modo che quando compiliamo il progetto, il compilatore trovi tutte le dipendenze e compili correttamente. Se manca una qualsiasi delle dipendenze, il compilatore fornisce un 'riferimento non definito'.
A parte le cause discusse sopra, l'errore 'riferimento indefinito' può verificarsi in molte altre situazioni. Ma la linea di fondo è che il programmatore ha sbagliato le cose e per evitare questo errore dovrebbero essere corretti.
password del router predefinito e elenco dei nomi utente
Errore di segmentazione (core dump)
L'errore 'segmentation fault (core dumped)' è un errore che indica un danneggiamento della memoria. Di solito si verifica quando si cerca di accedere a una memoria che non appartiene al programma in esame.
Ecco alcuni dei motivi che causano l'errore di errore di segmentazione.
# 1) Modifica della stringa costante
Considera il seguente programma in cui abbiamo dichiarato una stringa costante. Quindi proviamo a modificare questa stringa costante. Quando il programma viene eseguito, otteniamo l'errore mostrato nell'output.
#include int main() { char *str; //constant string str = 'STH'; //modifying constant string *(str+1) = 'c'; return 0; }
Produzione:
# 2) Dereferencing Pointer
Un puntatore deve puntare a una posizione di memoria valida prima di dereferenziarlo. Nel programma seguente, vediamo che il puntatore punta a NULL, il che significa che la posizione di memoria a cui punta è 0, ovvero non valida.
Quindi, quando lo dereferenziamo nella riga successiva, stiamo effettivamente cercando di accedere alla sua posizione di memoria sconosciuta. Ciò si traduce effettivamente in un errore di segmentazione.
#include using namespace std; int main() { int* ptr = NULL; //here we are accessing unknown memory location *ptr = 1; cout << *ptr; return 0; }
Produzione:
Errore di segmentazione
Il prossimo programma mostra un caso simile. Anche in questo programma, il puntatore non punta a dati validi. Un puntatore non inizializzato vale quanto NULL e quindi punta anche a una posizione di memoria sconosciuta. Pertanto, quando proviamo a dereferenziarlo, si ottiene un errore di segmentazione.
#include using namespace std; int main() { int *p; cout<<*p; return 0; }
Produzione:
Errore di segmentazione
Per evitare tali errori, dobbiamo assicurarci che le nostre variabili puntatore nel programma puntino sempre a posizioni di memoria valide.
# 3) Overflow dello stack
Quando abbiamo chiamate ricorsive nel nostro programma, consumano tutta la memoria nello stack e causano l'overflow dello stack. In questi casi, otteniamo l'errore di segmentazione poiché anche l'esaurimento della memoria dello stack è una sorta di danneggiamento della memoria.
Considera il programma seguente in cui calcoliamo ricorsivamente il fattoriale di un numero. Nota che la nostra condizione di base verifica se il numero è 0 e quindi restituisce 1. Questo programma funziona perfettamente per i numeri positivi.
Ma cosa succede quando passiamo effettivamente un numero negativo a una funzione fattoriale? Bene, poiché la condizione di base non viene fornita per i numeri negativi, la funzione non sa dove fermarsi e quindi si verifica un overflow dello stack.
Questo è mostrato nell'output di seguito che fornisce un errore di segmentazione.
#include using namespace std; int factorial(int n) { if(n == 0) { return 1; } return factorial(n-1) * n; } int main() { cout< Produzione:
Errore di segmentazione (core dump)
Ora, per correggere questo errore, modifichiamo leggermente la condizione di base e specifichiamo anche il caso per i numeri negativi come mostrato di seguito.
#include using namespace std; int factorial(int n) { // What about n <0? if(n <= 0) { return 1; } return factorial(n-1) * n; } int main() { cout<<'Factorial output:'< Produzione:
Output fattoriale: 1
Ora vediamo che l'errore di segmentazione è stato risolto e il programma funziona bene.
Simbolo esterno non risolto
Il simbolo esterno non risolto è un errore del linker che indica che non riesce a trovare il simbolo o il suo riferimento durante il processo di collegamento. L'errore è simile a 'riferimento non definito' e viene emesso in modo intercambiabile.
Di seguito abbiamo fornito due casi in cui può verificarsi questo errore.
# 1) Quando si fa riferimento a una variabile di struttura nel programma che contiene un membro statico.
#include struct C { static int s; }; // int C::s; // Uncomment the following line to fix the error. int main() { C c; C::s = 1; }
Produzione:
come testare una pagina web

Nel programma precedente, la struttura C ha un membro statico s che non è accessibile ai programmi esterni. Quindi, quando proviamo ad assegnargli un valore nella funzione principale, il linker non trova il simbolo e potrebbe risultare in un 'simbolo esterno non risolto' o 'riferimento non definito'.
Il modo per correggere questo errore è di definire l'ambito esplicito della variabile utilizzando '::' all'esterno del main prima di utilizzarlo.
# 2) Quando abbiamo variabili esterne referenziate nel file sorgente e non abbiamo collegato i file che definiscono queste variabili esterne.
Questo caso è illustrato di seguito:
#include #include using namespace std; extern int i; extern void g(); void f() { i++; g(); } int main() {}
Produzione:

In generale, nel caso di un 'simbolo esterno non risolto', il codice compilato per qualsiasi funzione simile a un oggetto non riesce a trovare un simbolo a cui fa riferimento, forse perché quel simbolo non è definito nei file oggetto o in nessuna delle librerie specificato al linker.
Conclusione
In questo tutorial, abbiamo discusso alcuni dei principali errori in C ++ che sono critici e possono influenzare il flusso del programma e potrebbero persino provocare un arresto anomalo dell'applicazione. Abbiamo esaminato in dettaglio tutto ciò che riguarda l'errore di segmentazione, il simbolo esterno non risolto e il riferimento non definito.
Sebbene questi errori possano verificarsi in qualsiasi momento, dalle cause che abbiamo discusso sappiamo che possiamo facilmente prevenirli sviluppando attentamente il nostro programma.
=> Leggere la serie di formazione Easy C ++.
Lettura consigliata