C언어로 스택(Stack)을 구현하며 다중 소스 파일 컴파일 시 발생하는
전형적인 링킹(Linking) 에러와 그 해결 과정 정리
1. 발생한 에러 상황
.h 헤더 파일에 전역 변수를 선언하고, 이를 여러 .c 파일에서 #include 했을 때 다음과 같은 에러가 발생합니다.
Bash
/usr/bin/ld: /tmp/ccieUva8.o:(.bss+0x0): multiple definition of `stack`;
/tmp/ccpgWox5.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

원인:
- stackS.h에 element stack[STACK_SIZE];라고 변수를 정의함.
- ex5-1.c와 stackS.c에서 각각 이 헤더를 포함함.
- 컴파일러는 각 소스 파일마다 stack이라는 메모리 공간을 따로 만듦.
- 링커(ld)가 파일들을 합칠 때 "똑같은 이름의 변수가 왜 두 개나 있어?"라며 충돌 발생.
2. 시도했던 해결 방법 (실패)
헤더 파일의 변수 선언 앞에 extern 키워드를 붙임.
C :
// stackS.h
extern element stack[STACK_SIZE];
수정 후 결과:
Bash
stackS.c:(.text+0x8d): undefined reference to `stack`

실패 이유:
extern은 "이 변수는 다른 어딘가에 실체가 있으니 찾아봐라"라는 예약 선언일 뿐입니다.
하지만 소스 파일(stackS.c) 어디에도 실제 변수 정의(메모리 할당)를 하지 않았기 때문에 링커가 실체를 찾지 못해 오류가 발생합니다.
3. 최종 해결 방법 (성공)
변수의 선언과 정의를 명확히 분리합니다.
① stackS.c (실제 정의)
실제 변수 공간을 이곳에만 만듭니다.
C
#include "stackS.h"
element stack[STACK_SIZE]; // 메모리 공간 할당 (정의)
void push(element item) { ... }
// ... 기타 함수 구현
② stackS.h (선언 삭제)
함수 안에서만 쓰기 때문에 아예 삭제합니다.
C
element stack[STACK_SIZE]; //삭제
③ 컴파일 완료 후 출력값 ^_________^

출력값 제대로 나올 때 마다 너무나 뿌듯
💡 요약 및 결론
| 구분 | 위치 | 설명 |
| 정의 (Definition) | .c 파일 | 실제 메모리 공간을 차지함. 딱 한 곳에만 존재해야 함. |
| 선언 (Declaration) | .h 파일 | "이런 변수가 존재한다"고 알려줌. extern 키워드 사용. |
결론: 전역 변수를 사용할 때는 헤더 파일에 직접 정의하지 마세요. .c 파일에서 변수를 만들고, 헤더 파일에서는 extern으로 소개만 하는 것이 정석입니다.
한마디: 컴파일러가 파일을 개별적으로 처리한 후, 나중에 링커가 하나로 합치는 과정을 이해하면 이런 에러를 쉽게 예방할 수 있습니다!
도움이 되셨다면 공감과 댓글 부탁드립니다!
출처 : C언어 자료구조 실습 사용교재 : C로 배우는 쉬운 자료구조(4판)(IT@COOKBOOK)
p.247 - 예제 5-1