컴파일 단계에서 라이브러리 위치를 연결했는데도 프로그램을 실행하기 전에 LD_LIBRARY_PATH를 설정해야 하는 이유는 무엇입니까? [복사]

컴파일 단계에서 라이브러리 위치를 연결했는데도 프로그램을 실행하기 전에 LD_LIBRARY_PATH를 설정해야 하는 이유는 무엇입니까? [복사]

나는 컴파일된 모델을 사용하고 있습니다 make. 이 모델에는 Makefile와 유사한 플래그를 통해 소스 코드를 종속 라이브러리와 연결하는 플래그가 있습니다 -L/lib1 -L/lib2. 하지만 모델을 실행하려고 하면 환경 변수도 확인하지 않으면 실패합니다.

export LD_LIBRARY_PATH=/lib1:/lib2

그리고 정확히 동일한 라이브러리를 가리킵니다. 이것은 나에게 중복되는 것 같습니다.

여기서 무슨 일이 일어나고 있는 걸까요? 컴파일 전과 실행 전에 라이브러리 위치를 지정해야 하는 이유는 무엇입니까?

이것은 아마도 어리석은 질문일 것입니다. 저는 기계 코드를 컴파일하는 데 경험이 많지 않으며 대개 스크립팅 언어를 사용합니다.

답변1

모든 사람이 구어체로 컴파일을 사용하여 소스 코드를 실행 파일로 변환하지만 기술적으로는 다소 긴 파이프라인의 한 단계일 뿐입니다.

  1. 입력 파일은 전처리기를 통해 실행되어 단일 번역 단위를 생성합니다.
  2. 전처리기의 출력은 어셈블리로 컴파일됩니다.
  3. 어셈블러는 이를 입력으로 받아들이고 객체 파일을 출력합니다.
  4. 링커는 개체 파일을 함께 연결하여 실행 파일을 생성합니다.

[엄밀히 말하면 이러한 단계를 분리할 필요가 없으며 현대 컴파일러는 효율성을 위해 종종 이를 결합합니다. ]

우리가 관심을 갖는 것은 코드를 표준 시스템 라이브러리와 결합하는 연결 단계입니다. 링커는 정적 라이브러리의 개체를 실행 파일로 직접 복사합니다. 그러나 공유 라이브러리의 경우 라이브러리에 대한 참조만 제공합니다.

공유 라이브러리에는 많은 장점이 있습니다. 프로그램을 다시 컴파일하지 않고도 업데이트할 수 있으며, 프로그램이 공통 코드를 공유할 수 있기 때문에 메모리를 덜 사용합니다. 또한 코드가 실행 파일에 없다는 명백한 단점도 있습니다.

솔루션은 런타임에 모든 공유 라이브러리 참조를 해결하는 동적 로더입니다. 로더는 자동으로 실행됩니다. 이를 수행하기 위한 지침은 링커가 실행 파일에 포함하는 것입니다. 물론 이는 로더가 이러한 라이브러리를 찾을 수 있다고 가정합니다.

시스템 라이브러리는 표준 디렉토리에 있으므로 쉽습니다. 그렇지 않은 경우 로더는 LD_LIBRARY_PATH를 검색합니다. 링커가 실행 파일에 경로를 입력하지 않는 이유는 무엇입니까? 왜냐하면 그러면 라이브러리를 이동하거나 변경할 수 없기 때문입니다.

실제로 라이브러리가 시스템 검색 경로 외부에 있기 때문에 실제로 실행 파일을 이동할 수도 없습니다. 라이브러리가 ~luke/lib에 있을 때만 실행된다면 joe가 파일을 읽을 수 없으면 joe에게 줄 수 없습니다. 새 직장을 구하면 조는 짜증이 난다.

참고로, 다른 다양한 방법으로도 흡수됩니다. 컴파일 타임에만 라이브러리 위치 등을 지정할 수 있다면 디버깅은 영원한 악몽이 될 것입니다.

관련 정보