c errors undefined reference
Овај водич детаљно описује критичне грешке са којима програмери често наилазе у Ц ++-у, попут Недефинисане референце, грешке сегментације (језгро бачено) и нерешеног спољног симбола:
Разговараћемо о најважнијим грешкама са којима се често сусрећемо у Ц ++-у, а које су заиста подједнако критичне. Поред системских и семантичких грешака и изузетака који се с времена на време јављају, добијамо и друге критичне грешке које утичу на покретање програма.
Ове грешке се углавном јављају пред крај програма током извођења. Понекад програм даје исправан излаз и тада дође до грешке.
=> Посетите овде да бисте научили Ц ++ из огреботина.
Шта ћете научити:
Важне грешке на Ц ++
У овом упутству ћемо размотрити три врсте грешака које су критичне са становишта било ког програмера Ц ++.
- Недефинисана референца
- Квар сегментације (језгро бачено)
- Нерешени спољни симбол
Разговараћемо о могућим узроцима сваке од ових грешака и заједно са мерама предострожности које можемо предузети као програмер да бисмо спречили ове грешке.
Почнимо!!
Недефинисана референца
До грешке „Недефинисана референца“ долази када у нашем програму имамо референцу на име објекта (класу, функцију, променљиву итд.), А повезивач не може да пронађе његову дефиницију када покушава да га потражи у свим повезаним објектним датотекама и библиотекама .
како отворити .јсон датотеке
Стога, када повезивач не може да нађе дефиницију повезаног објекта, издаје грешку „недефинисана референца“. Као што је јасно из дефиниције, ова грешка се јавља у каснијим фазама процеса повезивања. Постоје разни разлози који узрокују грешку „недефинисана референца“.
Неке од ових разлога разматрамо у наставку:
# 1) За објекат није дата дефиниција
Ово је најједноставнији разлог за узроковање грешке „недефинисане референце“. Програмер је једноставно заборавио да дефинише објекат.
Размотрите следећи програм Ц ++. Овде смо само навели прототип функције и затим га користили у главној функцији.
#include int func1(); int main() { func1(); }
Излаз:
Дакле, када компајлирамо овај програм, издаје се грешка у везивању која каже „недефинисана референца на„ фунц1 () “.
Да бисмо се решили ове грешке, исправљамо програм на следећи начин давањем дефиниције функције фунц1. Сада програм даје одговарајући излаз.
#include using namespace std; int func1(); int main() { func1(); } int func1(){ cout<<'hello, world!!'; }
Излаз:
Здраво Свете!!
# 2) Погрешна дефиниција (потписи се не подударају) коришћених објеката
Још један узрок грешке „недефинисане референце“ је када одредимо погрешне дефиниције. У нашем програму користимо било који објекат и његова дефиниција је нешто друго.
Размотрите следећи програм Ц ++. Овде смо позвали функц1 (). Његов прототип је инт фунц1 (). Али његова дефиниција се не поклапа са прототипом. Као што видимо, дефиниција функције садржи параметар функције.
Дакле, када се програм компајлира, компилација је успешна због подударања прототипа и позива функције. Али када повезивач покушава повезати позив функције са његовом дефиницијом, проналази проблем и грешку издаје као „недефинисану референцу“.
#include using namespace std; int func1(); int main() { func1(); } int func1(int n){ cout<<'hello, world!!'; }
Излаз:
Тако да бисмо спречили такве грешке, једноставно унакрсно проверимо да ли се дефиниције и употреба свих објеката подударају у нашем програму.
# 3) Датотеке објеката нису правилно повезане
Ово издање такође може довести до грешке „недефинисана референца“. Овде можемо имати више изворних датотека и можда их компајлирамо независно. Када се то уради, објекти нису правилно повезани и резултира „недефинисаном референцом“.
Размотрите следећа два програма Ц ++. У првој датотеци користимо функцију „принт ()“ која је дефинисана у другој датотеци. Када ове датотеке компајлирамо одвојено, прва датотека даје „недефинисану референцу“ за функцију штампања, док друга датотека даје „недефинисану референцу“ за главну функцију.
int print(); int main() { print(); }
Излаз:
int print() { return 42; }
Излаз:
Начин за решавање ове грешке је компајлирање обе датотеке истовремено ( На пример, коришћењем г ++).
Поред узрока о којима је већ било речи, „недефинисана референца“ може се јавити и из следећих разлога.
# 4) Погрешан тип пројекта
Када одредимо погрешне типове пројеката у Ц ++ ИДЕ-има попут визуалног студија и покушамо да урадимо ствари које пројекат не очекује, тада ћемо добити „недефинисану референцу“.
# 5) Нема библиотеке
Ако програмер није правилно одредио путању до библиотеке или је потпуно заборавио да је наведе, тада из библиотеке добијамо „недефинисану референцу“ за све референце које програм користи.
# 6) Зависни фајлови нису састављени
Програмер мора осигурати да претходно компајлирамо све зависности пројекта, тако да када компајлирамо пројекат, компајлер проналази све зависности и успешно их компајлира. Ако нека од зависности недостаје, онда преводилац даје „недефинисану референцу“.
Осим горе наведених узрока, грешка „недефинисана референца“ може се појавити у многим другим ситуацијама. Закључак је да је програмер погрешно схватио ствари и да би спречио ову грешку, требало би их исправити.
Грешка сегментације (језгро бачено)
Грешка „грешка сегментације (језгро бачено)“ је грешка која указује на оштећење меморије. Обично се јавља када покушамо да приступимо меморији која не припада програму који се разматра.
Ево неколико разлога који узрокују грешку грешке сегментације.
# 1) Измена константног низа
Размотрите следећи програм у коме смо прогласили константни низ. Затим покушавамо да модификујемо овај константни низ. Када се програм изврши, добивамо грешку приказану у излазу.
#include int main() { char *str; //constant string str = 'STH'; //modifying constant string *(str+1) = 'c'; return 0; }
Излаз:
# 2) Показивач за преусмеравање референце
Показивач мора усмерити на важећу меморијску локацију пре него што је одзначимо. У доњем програму видимо да показивач показује НУЛЛ, што значи да је меморијска локација на коју показује 0, тј. Неваљана.
Стога, када га преусмеримо у следећи ред, заправо покушавамо да приступимо његовој непознатој меморијској локацији. То заиста резултира грешком сегментације.
#include using namespace std; int main() { int* ptr = NULL; //here we are accessing unknown memory location *ptr = 1; cout << *ptr; return 0; }
Излаз:
Квар сегментације
Следећи програм приказује сличан случај. У овом програму такође показивач не показује важеће податке. Неиницијализовани показивач је добар као НУЛЛ и стога такође упућује на непознату меморијску локацију. Стога, када покушамо да га уклонимо, резултира грешком сегментације.
#include using namespace std; int main() { int *p; cout<<*p; return 0; }
Излаз:
Квар сегментације
Да бисмо спречили такве грешке, морамо осигурати да наше променљиве показивача у програму увек воде на важеће меморијске локације.
# 3) Преливање стека
Када у нашем програму имамо рекурзивне позиве, они поједу сву меморију у стеку и узрокују преливање стека. У таквим случајевима добијамо грешку сегментације јер је понестајање меморије стека такође врста оштећења меморије.
Размотрите доњи програм у којем израчунавамо факторијел броја рекурзивно. Имајте на уму да наши основни услови тестирају да ли је број 0, а затим враћа 1. Овај програм савршено функционише за позитивне бројеве.
Али шта се дешава када заправо пренесемо негативни број на факторску функцију? Па, како основни услов није дат за негативне бројеве, функција не зна где да се заустави и тиме резултира преливањем стека.
То је приказано у доњем излазу који даје грешку у сегментацији.
#include using namespace std; int factorial(int n) { if(n == 0) { return 1; } return factorial(n-1) * n; } int main() { cout< Излаз:
Квар сегментације (језгро бачено)
Сада да бисмо исправили ову грешку, мало мењамо основно стање и такође специфицирамо случај негативних бројева као што је приказано доле.
#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:'< Излаз:
Факторски излаз: 1
Сада видимо да је решена грешка сегментације и да програм ради у реду.
Нерешени спољни симбол
Нерешени спољни симбол је грешка повезивача која указује да не може да пронађе симбол или његову референцу током процеса повезивања. Грешка је слична „недефинисаној референци“ и издаје се наизменично.
У наставку смо навели два случаја где се ова грешка може догодити.
# 1) Када у програму упутимо структурну променљиву која садржи статичког члана.
#include struct C { static int s; }; // int C::s; // Uncomment the following line to fix the error. int main() { C c; C::s = 1; }
Излаз:

У горњем програму, структура Ц има статичке чланове с који нису доступни спољним програмима. Дакле, када му покушамо доделити вредност у главној функцији, повезивач не проналази симбол и може резултирати „нерешеним спољним симболом“ или „недефинисаном референцом“.
Начин да се поправи ова грешка је да се пре коришћења променљиве експлицитно опсеже помоћу „::“ изван главне.
# 2) Када имамо спољне променљиве на које се позива изворна датотека, а нисмо повезали датотеке које дефинишу ове спољне променљиве.
Овај случај је приказан у наставку:
#include #include using namespace std; extern int i; extern void g(); void f() { i++; g(); } int main() {}
Излаз:

Генерално, у случају „нерешеног спољног симбола“, компајлирани код било ког објекта попут функције не успева да пронађе симбол на који се позива, можда зато што тај симбол није дефинисан у објектним датотекама или било којој библиотеци назначено повезивачу.
Закључак
У овом упутству смо разговарали о неким главним грешкама у Ц ++-у које су критичне и могу утицати на ток програма и чак могу довести до пада система. Детаљно смо истражили све о грешци сегментације, нерешеном спољном симболу и недефинисаној референци.
Иако се ове грешке могу догодити било када, из узрока о којима смо разговарали знамо да их лако можемо спречити пажљивим развојем нашег програма.
=> Прочитајте серију Еаси Ц ++ Траининг Сериес.
Препоручено читање