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) 제대로 링크되지 않은 개체 파일
이 문제로 인해 'undefined reference'오류가 발생할 수도 있습니다. 여기에서 소스 파일이 두 개 이상있을 수 있으며 독립적으로 컴파일 할 수 있습니다. 이 작업이 완료되면 개체가 제대로 연결되지 않고 '정의되지 않은 참조'가됩니다.
다음 두 C ++ 프로그램을 고려하십시오. 첫 번째 파일에서는 두 번째 파일에 정의 된 '인쇄 ()'기능을 사용합니다. 이러한 파일을 개별적으로 컴파일 할 때 첫 번째 파일은 인쇄 기능에 대해 '정의되지 않은 참조'를 제공하고 두 번째 파일은 주 함수에 대해 '정의되지 않은 참조'를 제공합니다.
int print(); int main() { print(); }
산출:
int print() { return 42; }
산출:
이 오류를 해결하는 방법은 두 파일을 동시에 컴파일하는 것입니다 ( 예를 들면 g ++를 사용하여).
이미 논의 된 원인 외에도 다음과 같은 이유로 '정의되지 않은 참조'가 발생할 수도 있습니다.
# 4) 잘못된 프로젝트 유형
Visual Studio와 같은 C ++ IDE에서 잘못된 프로젝트 유형을 지정하고 프로젝트에서 예상하지 못한 작업을 시도하면 '정의되지 않은 참조'가 발생합니다.
# 5) 도서관 없음
프로그래머가 라이브러리 경로를 제대로 지정하지 않았거나 지정하는 것을 완전히 잊은 경우 프로그램이 라이브러리에서 사용하는 모든 참조에 대해 '정의되지 않은 참조'를 얻습니다.
# 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가 있습니다. 따라서 main 함수에서 값을 할당하려고 할 때 링커는 심볼을 찾지 못해 '확인되지 않은 외부 심볼'또는 '정의되지 않은 참조'가 될 수 있습니다.
이 오류를 수정하는 방법은 사용하기 전에 기본 외부에서‘::’를 사용하여 변수의 범위를 명시 적으로 지정하는 것입니다.
# 2) 소스 파일에서 참조되는 외부 변수가 있고 이러한 외부 변수를 정의하는 파일을 연결하지 않은 경우.
이 사례는 다음과 같습니다.
#include #include using namespace std; extern int i; extern void g(); void f() { i++; g(); } int main() {}
산출:
일반적으로 '해결되지 않은 외부 기호'의 경우 함수와 같은 객체에 대한 컴파일 된 코드는 해당 기호가 객체 파일이나 라이브러리에 정의되어 있지 않기 때문에 참조 할 기호를 찾지 못합니다. 링커에 지정됩니다.
결론
이 튜토리얼에서 우리는 C ++의 중요하고 프로그램 흐름에 영향을 미칠 수 있고 심지어 애플리케이션 충돌을 일으킬 수도있는 몇 가지 주요 오류에 대해 논의했습니다. 세분화 오류, 해결되지 않은 외부 기호 및 정의되지 않은 참조에 대한 모든 것을 자세히 살펴 보았습니다.
이러한 오류는 언제든지 발생할 수 있지만 논의한 원인으로 볼 때 프로그램을 신중하게 개발하여 쉽게 예방할 수 있음을 알고 있습니다.
추천 도서