Quick Flow
C는 각 .c 파일을 따로 object file로 컴파일한 뒤 링크합니다. 선언과 정의의 문제가 다른 단계에서 드러나므로, 오류 메시지의 단계를 먼저 구분합니다.
compile error는 현재 translation unit의 문법·선언·타입을, undefined reference는 링크에 넣지 않은 정의·라이브러리를, multiple definition은 두 곳에 둔 일반 정의를 먼저 확인합니다.
cc -Wall -Wextra -c main.c
cc -Wall -Wextra -c math_utils.c
cc main.o math_utils.o -o app각 -c 호출은 object file 하나를 만들고, 마지막 명령이 심볼을 연결해 실행 파일을 만듭니다. header에는 선언만 두고 일반 전역·함수 정의는 한 .c 파일에 둬야 합니다.
기본 흐름
컴파일은 각 .c 파일을 개별 오브젝트로 만드는 단계이고, 링크는 그 오브젝트 파일들을 묶어 최종 실행 파일을 만드는 단계입니다.
/* math_utils.h */
double difference(double a, double b);/* math_utils.c */
double difference(double a, double b) {
return a - b;
}컴파일 단계에서는 선언만 맞아도 넘어갈 수 있지만, 링크 단계에서는 실제 정의가 필요합니다.
각 .c 파일과 그 include 결과는 하나의 translation unit입니다. 선언과 정의의 타입이 호환되지 않으면 한 파일에서는 지나가도 다른 translation unit과 연결된 프로그램의 동작을 믿을 수 없습니다. 공용 선언은 복사하지 말고 하나의 헤더에서 공유합니다.
대표 오류
undefined reference는 선언은 봤지만 실제 정의를 최종 링크에서 못 찾은 경우입니다.
.o파일을 링크에 안 넣음- 라이브러리 옵션 누락
- 함수 이름이나 시그니처 불일치
multiple definition은 같은 심볼 정의가 둘 이상 있는 경우입니다.
- 헤더에 전역 변수 정의를 넣음
- 헤더에 일반 함수 본문을 넣음
정적 라이브러리를 직접 링크하는 도구체인에서는 보통 라이브러리가 그것을 참조하는 object 뒤에 와야 합니다. 실제 명령과 플랫폼의 linker 규칙은 다를 수 있으므로, undefined reference에서는 누락뿐 아니라 link order와 필요한 시스템 라이브러리도 확인합니다.
빠른 점검
- 컴파일 오류인지 링크 오류인지 먼저 구분합니다.
- 선언은 헤더, 정의는
.c에 둡니다. undefined reference는 정의를 못 찾은 경우입니다.multiple definition은 같은 심볼 정의가 여러 곳에 있는 경우입니다.- 헤더에 전역 변수 정의나 일반 함수 본문을 넣으면 링크 단계에서 크게 터지기 쉽습니다.
주의할 점
함수나 전역 변수를 헤더에 "정의"해 두면 컴파일은 지나가도 링크에서 크게 터집니다. C 빌드 문제는 종종 코드 문법보다 파일 배치와 심볼 소유권 문제라는 점을 먼저 의심하는 편이 좋습니다.
참고 링크
2 sources