c errors undefined reference
Цей підручник детально описує критичні помилки, з якими програмісти часто стикаються на мові C ++, такі як невизначена довідка, помилка сегментації (дамп ядра) та невирішений зовнішній символ:
Ми обговоримо найважливіші помилки, з якими ми часто стикаємось у C ++, і є справді настільки ж критичними. Окрім системних та семантичних помилок та винятків, які трапляються час від часу, ми також отримуємо інші критичні помилки, які впливають на роботу програм.
Ці помилки здебільшого трапляються під кінець програми під час виконання. Іноді програма видає належний результат, і тоді виникає помилка.
=> Завітайте сюди, щоб вивчити C ++ з нуля.
що таке ключ безпеки мережі
Що ви дізнаєтесь:
Важливі помилки на C ++
У цьому підручнику ми обговоримо три типи помилок, які є критичними з точки зору будь-якого програміста на C ++.
- Невизначена довідка
- Помилка сегментації (стрижень ядра)
- Невирішений зовнішній символ
Ми обговоримо можливі причини кожної з цих помилок, а також запобіжні заходи, які ми можемо застосувати як програміст для запобігання цим помилкам.
Давайте розпочнемо!!
Невизначена довідка
Помилка 'Невизначене посилання' виникає, коли в нашій програмі є посилання на ім'я об'єкта (клас, функція, змінна тощо), і компонувальник не може знайти його визначення, коли він намагається шукати його у всіх пов'язаних об'єктних файлах та бібліотеках .
Таким чином, коли компоновщик не може знайти визначення пов'язаного об'єкта, він видає помилку 'невизначене посилання'. Як видно з визначення, ця помилка виникає на пізніх стадіях процесу зв’язування. Існують різні причини, що спричиняють помилку 'невизначене посилання'.
Деякі з цих причин ми обговорюємо нижче:
# 1) Для об’єкта не передбачено визначення
Це найпростіша причина спричинення помилки 'невизначеного посилання'. Програміст просто забув визначити об'єкт.
Розглянемо наступну програму на C ++. Тут ми лише вказали прототип функції, а потім використали його в основній функції.
#include int func1(); int main() { func1(); }
Вихід:
Отже, коли ми компілюємо цю програму, видається помилка лінкера, яка говорить “невизначене посилання на‘ func1 () ’”.
Щоб позбутися цієї помилки, ми виправляємо програму таким чином, надаючи визначення функції func1. Тепер програма видає відповідний результат.
#include using namespace std; int func1(); int main() { func1(); } int func1(){ cout<<'hello, world!!'; }
Вихід:
Привіт Світ!!
# 2) Неправильне визначення (підписи не збігаються) використовуваних об’єктів
Ще однією причиною помилки „невизначеного посилання” є те, що ми вказуємо неправильні визначення. Ми використовуємо будь-який об’єкт у нашій програмі, і його визначення є дещо іншим.
Розглянемо наступну програму на C ++. Тут ми зателефонували func1 (). Його прототипом є int func1 (). Але його визначення не відповідає його прототипу. Як бачимо, визначення функції містить параметр функції.
Таким чином, коли програма компілюється, компіляція успішна через збіг прототипу та виклику функції. Але коли компонувальник намагається зв’язати виклик функції з її визначенням, він виявляє проблему та видає помилку як „невизначене посилання”.
#include using namespace std; int func1(); int main() { func1(); } int func1(int n){ cout<<'hello, world!!'; }
Вихід:
Таким чином, щоб запобігти таким помилкам, ми просто перевіряємо, чи відповідають визначення та використання всіх об’єктів у нашій програмі.
# 3) Файли об’єктів не пов’язані належним чином
Ця проблема також може спричинити помилку 'невизначене посилання'. Тут ми можемо мати більше одного вихідного файлу, і ми можемо скомпілювати їх самостійно. Коли це зроблено, об'єкти не пов'язані належним чином, і це призводить до 'невизначеного посилання'.
Розглянемо наступні дві програми на C ++. У першому файлі ми використовуємо функцію “print ()”, яка визначена у другому файлі. Коли ми компілюємо ці файли окремо, перший файл дає 'невизначене посилання' для функції друку, тоді як другий файл дає 'невизначене посилання' для основної функції.
int print(); int main() { print(); }
Вихід:
int print() { return 42; }
Вихід:
Спосіб вирішення цієї помилки полягає в компіляції обох файлів одночасно ( Наприклад, за допомогою g ++).
Окрім причин, про які вже йшлося, 'невизначене посилання' може також трапитися з наступних причин.
# 4) Неправильний тип проекту
Коли ми вказуємо неправильні типи проектів у середовищах розробки середовищ C ++, таких як Visual Studio, і намагаємось робити те, чого не очікує проект, тоді ми отримуємо 'невизначене посилання'.
No5) Відсутність бібліотеки
Якщо програміст не вказав належним чином шлях до бібліотеки або зовсім забув вказати його, тоді ми отримуємо “невизначене посилання” для всіх посилань, які програма використовує з бібліотеки.
# 6) Залежні файли не компілюються
Програміст повинен забезпечити, щоб ми заздалегідь компілювали всі залежності проекту, щоб, коли ми компілюємо проект, компілятор знаходив усі залежності та успішно компілюється. Якщо якась із залежностей відсутня, то компілятор видає “невизначене посилання”.
Окрім розглянутих вище причин, помилка 'невизначене посилання' може виникати в багатьох інших ситуаціях. Суть полягає в тому, що програміст неправильно зрозумів ситуацію, і щоб запобігти цій помилці, їх слід виправити.
Помилка сегментації (стрижень ядра)
Помилка 'помилка сегментації (ядро викинуто)' - це помилка, яка вказує на пошкодження пам'яті. Зазвичай це відбувається, коли ми намагаємось отримати доступ до пам'яті, яка не належить до програми, що розглядається.
Ось кілька причин, які спричиняють помилку помилки сегментації.
# 1) Зміна постійного рядка
Розглянемо наступну програму, де ми оголосили константний рядок. Потім ми намагаємось змінити цей константний рядок. Коли програма виконується, ми отримуємо помилку, показану на виході.
#include int main() { char *str; //constant string str = 'STH'; //modifying constant string *(str+1) = 'c'; return 0; }
Вихід:
# 2) Покажчик розмежування посилань
Покажчик повинен вказувати на дійсне місце в пам'яті, перш ніж ми його будемо розмежовувати. У наведеній нижче програмі ми бачимо, що вказівник вказує на NULL, що означає, що розташування пам'яті, на яке він вказує, дорівнює 0, тобто недійсне.
Отже, коли ми розподіляємо його з наступного рядка, ми фактично намагаємось отримати доступ до його невідомого місця в пам'яті. Це справді призводить до помилки сегментації.
#include using namespace std; int main() { int* ptr = NULL; //here we are accessing unknown memory location *ptr = 1; cout << *ptr; return 0; }
Вихід:
Помилка сегментації
Наступна програма показує подібний випадок. У цій програмі вказівник також не вказує на дійсні дані. Неініціалізований вказівник такий же хороший, як NULL, а отже, він також вказує на невідоме розташування пам'яті. Таким чином, коли ми намагаємося розмежувати його, це призводить до помилки сегментації.
#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; }
Вихід:

У вищезазначеній програмі структура C має статичний член s, який не доступний для зовнішніх програм. Отже, коли ми намагаємося призначити йому значення в основній функції, компонувальник не знаходить символу і може призвести до «невирішеного зовнішнього символу» або «невизначеного посилання».
Спосіб виправлення цієї помилки полягає у явному застосуванні змінної, використовуючи ‘::’ поза головною перед її використанням.
# 2) Коли у нас є посилання на зовнішні змінні у вихідному файлі, і ми не пов’язали файли, що визначають ці зовнішні змінні.
Цей випадок продемонстровано нижче:
#include #include using namespace std; extern int i; extern void g(); void f() { i++; g(); } int main() {}
Вихід:
передача масиву методу в Java

Загалом, у випадку з «невирішеним зовнішнім символом», скомпільований код для будь-якого об'єкта, такого як функція, не знаходить символу, на який робить посилання, можливо тому, що цей символ не визначений у файлах об'єктів або будь-якій з бібліотек вказаний лінкеру.
Висновок
У цьому підручнику ми обговорили деякі основні помилки в C ++, які є критичними та можуть вплинути на потік програми і навіть можуть призвести до збою програми. Ми детально вивчили все про помилку сегментації, невирішений зовнішній символ та невизначену посилання.
Хоча ці помилки можуть виникати в будь-який час, з причин, про які ми говорили, ми знаємо, що їх легко запобігти, ретельно розробляючи нашу програму.
=> Прочитайте серію навчальних програм Easy C ++.
Рекомендована література