동일한 기호 중 일부를 사용하여 두 개의 공유 라이브러리 연결
2개의 다른 공유 라이브러리와 링크합니다.두 라이브러리 모두 이름은 공유하지만 구현이 서로 다른 기호를 정의합니다.각 라이브러리가 다른 라이브러리보다 자체 구현을 사용하도록 할 수 없습니다.
를 들어,두 모두 함수인 '만', '만', '만'을 합니다.bar()
각자가 내부적으로 전화를 걸죠.라고 부릅니다.foo1()
는 "2"에서 합니다.foo2()
.
Lib1.so:
T bar
T foo1() // calls bar()
Lib2.so:
T bar
T foo2() // calls bar()
so에 so에 하면 "Lib1"을 so에서 됩니다.즉, Lib2입니다.Lib1이 됩니다.소우토우토우토우토우토우토우토우토우토우토우토우타foo2()
Lib2.so, Lib2.Lib1 입니다.에 so so so so so so so so so so so
도서관이 항상 다른 어떤 도서관보다 자신의 구현을 선호하도록 하는 방법이 있을까요?
이 문제를 해결하려면 몇 가지 방법이 있습니다.
또는 링커에 전달합니다.이것은 글로벌한 효과가 있습니다.모든 참조는 글로벌한 기호(기능 타입의 경우)에 대한 것입니다.
-Bsymbolic-functions
라이브러리에서 기호로 확인할 수 있는 )는 해당 기호로 해결됩니다.이렇게 하면 LD_PRELOAD를 사용하여 이러한 심볼에 대한 내부 라이브러리 호출을 인터럽트할 수 없게 됩니다.기호는 라이브러리 외부에서 참조할 수 있도록 내보내집니다.버전 스크립트를 사용하여 기호를 라이브러리의 로컬로 표시합니다. 예를 들어 다음과 같습니다.
{local: bar;};
--version-script=versionfile
링커에 접속합니다.기호는 내보내지 않습니다.숨김, 내부 또는 보호되는 승인 가시성(가시성을 위한 GCC 정보 페이지)으로 기호를 표시합니다.보호된 가시성 기호는 로 내보내고, 숨겨진 기호는 내보내지 않으며, 내부 기호는 내보내지 않으므로 함수 포인터를 통해 간접적으로라도 라이브러리 외부에서 호출하지 않도록 해야 합니다.
할 수 .objdump -T
.
기존 립마다 하나씩 두 개의 '포장' 공유 립을 생성해야 합니다.각 기호는 API를 정의하는 몇 가지 충돌하지 않는 기호만 나열하는 --dynamic-list를 사용하여 구축해야 합니다.또한 글로벌 조합을 피하기 위해 -Bsymbolic이 필요합니다.
적절한 옵션을 사용하여 dlopen을 통해 결과 libs에 액세스하는 것도 스트레스를 덜 받을 수 있습니다.
이 문제를 해결하는 또 다른 방법은 매크로를 사용하여 네임스페이스를 변경하는 것입니다.
전제 조건
- 모든 요소(함수, 클래스, 전역 변수 등)가 네임스페이스에 있습니다.
- 라이브러리는 헤더의 매크로에 크게 의존하지 않습니다.
솔루션
- 라이브러리를 컴파일할 때 네임스페이스 이름으로 매크로를 정의하여 다른 이름으로 정의합니다.예를 들어 네임스페이스가 LibNS인 경우
-DLibNS=LibNSv1
한 케이스에 대해서-DLibNS=LibNSv2
상대방을 위해서. 코드에서 라이브러리를 사용할 경우 현재 상황에 따라 매크로를 정의합니다.
#define LibNS LibNSv1 #include "my_lib.h" #undef LibNS
다른 솔루션 대신 이 솔루션을 사용하는 이유
- 문제가 있는 라이브러리가 헤더 파일(예: 템플릿, 인라인 등)에서 사용되는 경우, 실행 파일의 코드에 포함시키면 해결사는 이러한 함수를 Lib1.so에서 호출해야 하는지 Lib2.so에서 호출해야 하는지 알 수 없습니다.
- 사용 중인 컴파일러는 다른 솔루션에 대한 지원이 부족하거나 전혀 없습니다(인텔/AMD 32/64비트 CPU에서는 발생하지 않아야 합니다만, Google 검색 결과 일부 다른 플랫폼에서 문제가 발생할 수 있습니다).
잠재적인 문제
- 실행 파일의 1개의 cpp 파일에서 두 버전을 모두 사용하면 문제가 발생할 수 있습니다.
#include "my_lib.h"
는 아마도 매크로를 사용하여 여러 개의 매크로로부터 보호하고 이를 피하기 위해 매크로를 정의하지 않으면 여러 가지 문제가 발생할 수 있습니다(앞으로 매크로 이름을 변경할 수 있습니다.헤더는 다른 매크로를 정의하는 등). - 이름
LibNS
라이브러리의 다른 것(기능, 기능 등)에 사용할 수 있습니다.이 경우 이 이름도 로 변경됩니다.LibNSv1
또는LibNSv2
라이브러리와 사용 방법에 따라 다른 문제가 발생할 수 있습니다.
메모들
- 이는 현재 받아들여지고 있는 답변(ninjalj; 자유롭게 복사 붙여넣기)을 대체하는 것이 아니라 다른 접근방식으로 확장하기 위한 것입니다.
- 제가 이 답변을 올린 주된 이유는 오늘 이 문제가 발생했기 때문입니다만, 헤더 파일에 문제가 있는 코드가 있기 때문에 답변이 도움이 되지 않았습니다.
- 출처 : https://spin.atomicobject.com/2014/06/03/static-linking-c-plus-plus/
언급URL : https://stackoverflow.com/questions/6538501/linking-two-shared-libraries-with-some-of-the-same-symbols
'programing' 카테고리의 다른 글
스프링 MVC - Rest 컨트롤러에서 단순 문자열을 JSON으로 반환하는 방법 (0) | 2022.08.17 |
---|---|
데이터 로드 처리 - Vue (0) | 2022.08.17 |
Java에서 현재 연도의 정수 값을 가져옵니다. (0) | 2022.08.14 |
MySQL 데이터베이스에 연결할 때 SSL 연결에 대한 경고 (0) | 2022.08.14 |
Vuex 스토어에서 상수 가져오기 (0) | 2022.08.14 |