c errors undefined reference
Ten samouczek szczegółowo opisuje krytyczne błędy, które programiści często napotykają w C ++, takie jak niezdefiniowane odwołanie, błąd segmentacji (zrzut rdzenia) i nierozwiązany symbol zewnętrzny:
Omówimy najważniejsze błędy, które często napotykamy w C ++, a które są równie krytyczne. Oprócz błędów systemowych i semantycznych oraz wyjątków, które pojawiają się od czasu do czasu, otrzymujemy również inne krytyczne błędy, które mają wpływ na działanie programów.
Te błędy występują najczęściej pod koniec programu w czasie wykonywania. Czasami program daje prawidłowe wyjście, a następnie pojawia się błąd.
=> Odwiedź tutaj, aby nauczyć się C ++ od podstaw.
Czego się nauczysz:
Ważne błędy C ++
W tym samouczku omówimy trzy typy błędów, które są krytyczne z punktu widzenia każdego programisty C ++.
- Niezdefiniowane odniesienie
- Błąd segmentacji (zrzucony rdzeń)
- Nierozwiązany symbol zewnętrzny
Omówimy możliwe przyczyny każdego z tych błędów oraz środki ostrożności, które jako programista możemy podjąć, aby zapobiec tym błędom.
Zaczynajmy!!
Niezdefiniowane odniesienie
Błąd „Niezdefiniowane odwołanie” występuje, gdy w naszym programie mamy odniesienie do nazwy obiektu (klasy, funkcji, zmiennej itp.), A konsolidator nie może znaleźć jego definicji, gdy próbuje go wyszukać we wszystkich połączonych plikach obiektów i bibliotekach .
Zatem gdy konsolidator nie może znaleźć definicji obiektu połączonego, generuje błąd „niezdefiniowane odwołanie”. Jak wynika z definicji, ten błąd występuje na późniejszych etapach procesu łączenia. Istnieje wiele przyczyn powodujących błąd „niezdefiniowanego odniesienia”.
Poniżej omawiamy niektóre z tych powodów:
1) Brak definicji obiektu
To jest najprostszy powód spowodowania błędu „niezdefiniowanego odniesienia”. Programista po prostu zapomniał zdefiniować obiekt.
Rozważmy następujący program w C ++. Tutaj określiliśmy tylko prototyp funkcji, a następnie użyliśmy go w funkcji głównej.
#include int func1(); int main() { func1(); }
Wynik:
Więc kiedy kompilujemy ten program, pojawia się błąd konsolidatora, który mówi „niezdefiniowane odwołanie do„ func1 () ””.
Aby pozbyć się tego błędu, poprawiamy program w następujący sposób, podając definicję funkcji func1. Teraz program podaje odpowiednie wyjście.
#include using namespace std; int func1(); int main() { func1(); } int func1(){ cout<<'hello, world!!'; }
Wynik:
Witaj świecie!!
2) Niewłaściwa definicja (niezgodność podpisów) używanych obiektów
Kolejną przyczyną błędu „niezdefiniowanego odniesienia” jest podanie błędnych definicji. W naszym programie używamy dowolnego obiektu, a jego definicja jest inna.
Rozważmy następujący program w C ++. Tutaj wywołaliśmy func1 (). Jego prototypem jest int func1 (). Ale jego definicja nie pasuje do jego prototypu. Jak widzimy, definicja funkcji zawiera parametr funkcji.
Zatem, gdy program jest kompilowany, kompilacja kończy się pomyślnie, ponieważ prototyp i wywołanie funkcji są zgodne. Ale kiedy konsolidator próbuje połączyć wywołanie funkcji z jej definicją, znajduje problem i wystawia błąd jako „niezdefiniowane odniesienie”.
#include using namespace std; int func1(); int main() { func1(); } int func1(int n){ cout<<'hello, world!!'; }
Wynik:
Dlatego, aby zapobiec takim błędom, po prostu sprawdzamy, czy definicje i użycie wszystkich obiektów są zgodne w naszym programie.
# 3) Pliki obiektów niepoprawnie połączone
Ten problem może również powodować błąd „niezdefiniowanego odniesienia”. Tutaj możemy mieć więcej niż jeden plik źródłowy i możemy je niezależnie skompilować. Po wykonaniu tej czynności obiekty nie są poprawnie połączone i powoduje powstanie „niezdefiniowanego odniesienia”.
Rozważ następujące dwa programy w C ++. W pierwszym pliku korzystamy z funkcji „print ()”, która jest zdefiniowana w drugim pliku. Kiedy kompilujemy te pliki oddzielnie, pierwszy plik podaje „niezdefiniowane odniesienie” dla funkcji drukowania, podczas gdy drugi plik zawiera „niezdefiniowane odniesienie” dla funkcji głównej.
int print(); int main() { print(); }
Wynik:
gdzie oglądać anime za darmo
int print() { return 42; }
Wynik:
Sposobem na rozwiązanie tego błędu jest jednoczesna kompilacja obu plików ( Na przykład, używając g ++).
Oprócz omówionych już przyczyn, „odwołanie nieokreślone” może wystąpić również z następujących powodów.
# 4) Niewłaściwy typ projektu
Kiedy określimy niewłaściwe typy projektów w C ++ IDE, takich jak Visual Studio, i spróbujemy zrobić rzeczy, których projekt nie oczekuje, otrzymujemy „niezdefiniowane odniesienie”.
# 5) Brak biblioteki
Jeśli programista nie określił poprawnie ścieżki do biblioteki lub całkowicie zapomniał ją określić, wówczas otrzymujemy „niezdefiniowane odniesienie” dla wszystkich referencji, których używa program z biblioteki.
# 6) Zależne pliki nie są kompilowane
Programista musi upewnić się, że wcześniej skompilowaliśmy wszystkie zależności projektu, tak aby podczas kompilacji projektu kompilator znalazł wszystkie zależności i pomyślnie się skompilował. Jeśli brakuje którejkolwiek z zależności, kompilator podaje „niezdefiniowane odniesienie”.
Oprócz przyczyn omówionych powyżej, błąd „niezdefiniowanego odniesienia” może wystąpić w wielu innych sytuacjach. Ale najważniejsze jest to, że programista pomylił się i aby zapobiec temu błędowi, powinien zostać poprawiony.
Usterka segmentacji (zrzucony rdzeń)
Błąd „błąd segmentacji (zrzut rdzenia)” to błąd wskazujący na uszkodzenie pamięci. Zwykle występuje, gdy próbujemy uzyskać dostęp do pamięci, która nie należy do rozważanego programu.
Oto niektóre przyczyny powodujące błąd błędu segmentacji.
# 1) Modyfikacja stałego ciągu
Rozważmy następujący program, w którym zadeklarowaliśmy stały ciąg. Następnie próbujemy zmodyfikować ten stały ciąg. Kiedy program jest wykonywany, otrzymujemy błąd pokazany na wyjściu.
#include int main() { char *str; //constant string str = 'STH'; //modifying constant string *(str+1) = 'c'; return 0; }
Wynik:
# 2) Wskaźnik dereferencji
Wskaźnik musi wskazywać prawidłową lokalizację w pamięci, zanim ją wyłuskujemy. W poniższym programie widzimy, że wskaźnik wskazuje na NULL, co oznacza, że miejsce w pamięci, na które wskazuje, jest 0, czyli nieprawidłowe.
Dlatego kiedy wyłuskujemy go w następnym wierszu, w rzeczywistości próbujemy uzyskać dostęp do jego nieznanej lokalizacji w pamięci. To rzeczywiście prowadzi do błędu segmentacji.
#include using namespace std; int main() { int* ptr = NULL; //here we are accessing unknown memory location *ptr = 1; cout << *ptr; return 0; }
Wynik:
Błąd segmentacji
Następny program pokazuje podobny przypadek. Również w tym programie wskaźnik nie wskazuje prawidłowych danych. Niezainicjowany wskaźnik jest tak dobry, jak NULL, a zatem wskazuje również na nieznane miejsce w pamięci. Tak więc, kiedy próbujemy go wyodrębnić, skutkuje to błędem segmentacji.
#include using namespace std; int main() { int *p; cout<<*p; return 0; }
Wynik:
Błąd segmentacji
Aby zapobiec takim błędom, musimy upewnić się, że nasze zmienne wskaźnikowe w programie zawsze wskazują prawidłowe miejsca w pamięci.
# 3) Przepełnienie stosu
Kiedy mamy wywołania rekurencyjne w naszym programie, pochłaniają one całą pamięć stosu i powodują przepełnienie stosu. W takich przypadkach otrzymujemy błąd segmentacji, ponieważ brak pamięci stosu jest również rodzajem uszkodzenia pamięci.
Rozważmy poniższy program, w którym rekurencyjnie obliczamy silnię liczby. Zwróć uwagę, że nasz warunek podstawowy sprawdza, czy liczba jest równa 0, a następnie zwraca 1. Ten program działa doskonale dla liczb dodatnich.
Ale co się stanie, gdy faktycznie przekażemy liczbę ujemną do funkcji silni? Cóż, ponieważ warunek podstawowy nie jest podany dla liczb ujemnych, funkcja nie wie, gdzie się zatrzymać, a tym samym powoduje przepełnienie stosu.
Jest to pokazane na poniższym wyjściu, które podaje błąd segmentacji.
#include using namespace std; int factorial(int n) { if(n == 0) { return 1; } return factorial(n-1) * n; } int main() { cout< Wynik:
Błąd segmentacji (zrzucony rdzeń)
Teraz, aby naprawić ten błąd, nieznacznie zmieniamy warunek podstawowy, a także określamy wielkość liter dla liczb ujemnych, jak pokazano poniżej.
#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:'< Wynik:
Wydajność silnia: 1
Teraz widzimy, że błąd segmentacji został rozwiązany i program działa dobrze.
Nierozwiązany symbol zewnętrzny
Nierozwiązany symbol zewnętrzny jest błędem konsolidatora, który wskazuje, że nie może znaleźć symbolu lub jego odniesienia podczas procesu łączenia. Błąd jest podobny do „niezdefiniowanego odniesienia” i jest wystawiany zamiennie.
Poniżej podano dwa przypadki, w których ten błąd może wystąpić.
# 1) Kiedy odnosimy się do zmiennej strukturalnej w programie, która zawiera statyczny element członkowski.
#include struct C { static int s; }; // int C::s; // Uncomment the following line to fix the error. int main() { C c; C::s = 1; }
Wynik:
W powyższym programie struktura C ma statyczne składowe, które nie są dostępne dla programów zewnętrznych. Więc kiedy próbujemy przypisać mu wartość w funkcji głównej, konsolidator nie znajduje symbolu i może skutkować „nierozwiązanym symbolem zewnętrznym” lub „niezdefiniowanym odniesieniem”.
Sposobem naprawienia tego błędu jest jawne określenie zakresu zmiennej za pomocą „::” poza main przed jej użyciem.
# 2) Kiedy mamy odniesienia do zmiennych zewnętrznych w pliku źródłowym i nie połączyliśmy plików, które definiują te zmienne zewnętrzne.
Ten przypadek jest przedstawiony poniżej:
#include #include using namespace std; extern int i; extern void g(); void f() { i++; g(); } int main() {}
Wynik:
jak stworzyć projekt java w eclipse
Ogólnie rzecz biorąc, w przypadku „nierozwiązanego symbolu zewnętrznego”, skompilowany kod dla dowolnego obiektu, takiego jak funkcja, nie może znaleźć symbolu, do którego się odwołuje, być może dlatego, że ten symbol nie jest zdefiniowany w plikach obiektowych lub żadnej z bibliotek określone dla konsolidatora.
Wniosek
W tym samouczku omówiliśmy kilka poważnych błędów w C ++, które są krytyczne i mogą wpływać na przepływ programu, a nawet powodować awarię aplikacji. Szczegółowo zbadaliśmy wszystko na temat błędu segmentacji, nierozwiązanego symbolu zewnętrznego i niezdefiniowanego odniesienia.
Chociaż te błędy mogą wystąpić w dowolnym momencie, z przyczyn, które omówiliśmy, wiemy, że możemy im łatwo zapobiec, starannie rozwijając nasz program.
=> Przeczytaj serię szkoleń Easy C ++.
rekomendowane lektury