C언어 에러 종류

2022. 2. 4. 02:18IoT Embeded 강의

#에러의 종류

이번에는 코딩을 하면서 발생하는 오류 3가지를 정리하겠습니다. 저도 비전공자에 코딩을 배운 기간이 짧아 다소 부족한 내용일 수 있습니다. 

 

1. 컴파일 에러 

개발자가 작성한 소스코드에서 컴파일이 이를 기계어로 번역해줍니다. 이 과정에서 지켜야 하는 소스 코드 언어의 규칙이 있습니다. 이러한 문법을 어기고 잘못된 방법으로 소스코드를 작성하는 것을 컴파일 에러라고 생각할 수 있습니다. 내 손이 실수했다고 생각하면 편합니다. 가장 흔히 발생하는 예로 키워드식별자의 철자를 틀리게 쓰는 경우입니다.

키워드 : 문법적으로 의미가 정해져 있는 단어 ex) if, else, for, while, void

식별자 : 함수이름, 변수이름과 같이 개발자가 마음대로 이름을 지어 사용하는 것 ex) int x, int y, int MyFunction(x,y)

 

#include <stdio.h>

 

int main()

{

        int ras;

        ras = 10;

        printf("%d", rsa);

        return 0;

}

 

위의 소스코드를 보면 변수를 선언할때는 int ras 로 선언한 뒤 함수에 사용할 때는 rsa로 썼습니다. 이처럼 철자를 틀리면 컴파일 에러가 나타납니다.

 

또한 헤더파일의 선언 없이 그 안에 들어있는 함수들을 바로 사용하는 것도 컴파일 에러의 원인입니다. 헤더파일은 함수들의 리턴형, 함수 이름, 입력 형식 등이 선언되어 있는 일종의 모음집이라고 할 수 있습니다. 때문에 헤더파일 하나만 선언해도 그 안에 다양한 함수들을 사용할 수 있게 됩니다. 따라서 헤더파일 선언 없이 함수를 사용하는 것은 함수 선언 없이 사용한 것과 같으므로 컴파일 에러가 나타납니다.

 

또한 형식지정자의 오용, 참조 연산자, 멤버 연산자 등의 사용법을 잘못 적용한 경우에도 컴파일 에러가 일어나는 경우가 많습니다. 컴파일 에러에서 특히 문법적인 오류인 경우에는 오류 사항을 개발환경에서 제대로 표시해주기 때문에 언어 문법과 자료형에 대한 공부, 검색 등을 통해 개선해나갈 수 있습니다.  

 

int main()

{

        int ras;

        ras = 10;

        printf("%d", ras);

        return 0;

}

 

위의 소스코드에서 #include <stdio.h> 라는 문장이 없습니다. #include <헤더파일명.h>는 헤더파일을 현재 작성하고 있는 소스코드에 사용한다는 의미입니다. <stdio.h>는 Standard input output의 약자로 표준 입출력과 관련된 함수와 기능들이 작성되어 있는 헤더 파일입니다. 여기서 printf의 함수에 대한 선언과 기능이 담겨 있는데 이 헤더파일을 사용하지 않아 printf라는 함수를 사용할 수 없는 것입니다. 

 

2. 링크에러

작성한 코드에 문법적으로 오류가 없고 철자도 맞게 써도 링크하는 과정에서 에러가 발생할 수 있습니다.

 

#include <stdio.h>

 

void print(char *string);

 

int main(void)

{

        print("Hello\n");

        return 0;

}

 

위의 코드에서 헤더파일을 선언하지 않았지만 print 라는 함수를 선언을 했기때문에 문법적으로는 문제가 없어 컴파일 에러는 나타나지 않습니다. 하지만 print라는 함수를 라이브러리에서 찾을 수 없기 때문에 함수를 호출하더라도 함수안에 실행할 명령어들을 찾지 못해 링크 에러가 나타나게 됩니다. 

 

3. 런타임 에러

컴파일과 링크 과정을 무사히 마치면 실행파일이 만들어집니다. 하지만 결과를 확인했을 때 개발자의 의도와는 다른 결과가 나올 수 있는데 이를 런타임 에러라고 합니다. 흔히 버그라고 부르고, 버그를 찾아서 제거하는 과정을 디버깅이라고 합니다.

 

간단하게 예를 들어 printf 함수를 이용해 "Hello" 라는 문구를 출력한다고 했을 때 제가 오타로 "Hallo" 라고 입력했다고 가정해보겠습니다.

 

#include <stdio.h>

 

int main(void)

{

        printf("Hallo");

        return 0;

}

 

제가 생각한 결과는 "Hello" 이지만 실제 출력화면은 "Hallo" 입니다. 여기서 컴파일, 링크 과정에는 전혀 문제가 없기 때문에 프로그램은 따로 오류의 위치와 내용을 알리지 않고 정상적으로 작동합니다. 때문에 저는 소스코드를 확인하여 "Hallo"를 찾아내어 오류를 수정할 것입니다. 간단한 프로그램에서는 사소해보이지만 만약 "Hello" 라는 결과값을 이용해 다른 함수에 입력시켜 그 함수를 작동시켜야 한다면 어떨까요? 아마 그 함수는 제대로 작동하지 않을 것입니다. 더해서 더 복잡하게 여러 함수, 기능들이 서로 연관되어 있다면 사태는 더욱 커질 것입니다. 

이런 상황을 위해 디버깅을 해주는 도구인 디버거가 있습니다. 런타임 에러가 있을 때는 직접 소스코드를 노려보며 찾지 말고 디버거를 이용해야 합니다.

'IoT Embeded 강의' 카테고리의 다른 글

반복문의 기본 문법  (0) 2022.02.08
조건문의 기본 문법  (0) 2022.02.07
컴퓨터의 구조와 CPU동작 원리  (0) 2022.02.04
디지털 논리회로  (0) 2022.01.29
하드웨어의 이해  (0) 2022.01.29