-
pragma once는 만능이 아니다개발/C·C++ 2019. 9. 17. 21:33
pragma once 전처리기는 인클루드가 수행될 때 반복되는 걸 막는 기능을 할 뿐이다. pragma once를 사용했는데도 비주얼 스튜디오에서 LNK2005 오류가 발생하는 이유다. 소스코드의 빌드는 크게 세 가지 과정을 거친다. 전처리, 컴파일, 링킹으로 나눌 수 있는데, 전처리 과정에서는 소스 파일(cpp)에 있는 pragma, include, define 등의 지시자를 처리한다.
전처리 과정에서 문제가 없었으면 컴파일러는 전처리기기가 모두 코드로 대체된 순수한 C++ 소스 코드를 파싱해 어셈블리 코드로 만든다. 그다음에 기계 코드로 번역해 바이너리 파일을 만드는데 이것이 오브젝트 파일이다(.obj). 각각의 소스 코드 별로 독립적으로 컴파일이 완료되면 각각의 오브젝트 파일이 생성된다.
마지막으로 링커는 컴파일러가 만든 오브젝트 파일로부터 최종 결과물을 만든다. 라이브러리 파일이 되거나 실행 파일이 되거나. 모든 오브젝트 파일을 연결하는데, 레퍼런스를 올바른 주소를 가진 정의되지 않은 심볼로 대체한다. 각각의 심볼은 다른 오브젝트 파일이나 라이브러리에서 정의될 수 있다. 표준 라이브러리가 아닌 라이브러리로 정의되는 상황이라면 링커에게 그 사실을 알릴 필요가 있다.
이 단계에서 발생하는 흔한 오류는 정의를 찾을 수 없는 경우와 중복 정의다. 전자는 정의가 존재하지 않거나, 정의가 존재하는 오브젝트 파일이나 라이브러리를 링커에게 알리지 않았을 때 일어난다. 후자의 원인은 꽤 명백한데, 심볼이 다른 두 곳의 오브젝트 파일이나 라이브러리에서 중복 정의되었기 때문이다.
헤더 파일에 전역 변수를 선언하고 정의를 했거나, extern 키워드를 붙이지 않은 경우, 함수 선언만 있는 순수한 헤더가 아닐 경우에 중복 정의 문제가 발생하게 된다. 전역 변수의 정의를 소스 파일로 옮기고 함수의 정의부도 소스 파일로 옮기면 문제가 해결되는데, 헤더의 소스양이 많아 분리하는 게 부담되는 일이 있다. 이때에는 소스 파일에서 반드시 한 번만 인클루드되도록 설계를 잘하는 수밖에 없다.
'개발 > C·C++' 카테고리의 다른 글
구조체 바이트 정렬은 만능이 아니다 (0) 2019.10.19 간과할 수 있는 문자열 비교 실수 (0) 2019.10.01 미리 컴파일된 헤더를 쓰면서 생긴 문제 하나 (0) 2019.09.14 미리 컴파일된 헤더 오류 (0) 2019.08.20 이 작업을 수행하기 위해 이 파일과 연결된 앱이 없습니다 (0) 2019.08.20