공유 라이브러리에서 동적으로 링크 될 때 전역 및 정적 변수는 어떻게?
전역 변수와 정적 변수가있는 모듈이 응용 프로그램에 동적으로 연결되는 방식을 이해하려고합니다. 모듈은 솔루션의 각 프로젝트를 의미합니다 (Visual Studio에서 많은 작업을 수행합니다!). 이 모듈은 * .lib 또는 * .dll 또는 * .exe 자체에 내장되어 있습니다.
응용 프로그램의 이진에는 데이터 세그먼트의 모든 인화 변환 단위 (개체 파일)의 전역 및 정적 데이터가 포함되어 상수 인 경우 데이터 세그먼트 만 읽습니다.
이 애플리케이션이로드 동적 링크가있는 모듈 A를 사용하면 어떻게 검증? DLL에 정적 및 정적 섹션이 가정합니다. 운영 창고가로드? 어디에 어디에 저장?
그리고 애플리케이션이 작동하는 동적 링크가있는 모듈 B를 사용하면 어떻게 검증됩니까?
응용 프로그램에 A와 B를 모두 사용하는 두 개의 모듈이있는 경우 A와 B의 전역 복사본이 아래에 언급 된 것처럼 생성됨 (다른 프로세스 인 경우)?
DLL A와 B는 응용 프로그램 전역에 액세스 할 수 있습니까?
(이유도 설명 해주세요)
MSDN 에서 인용 :
DLL 소스 코드 파일에서 전역으로 선언 된 변수는 컴파일러와 링커에 의해 전역 변수로 취급 설명 지정된 DLL을로드하는 각 프로세스는 해당 DLL 전역 변수의 자체 복사본을 가져옵니다. 정적 변수의 범위는 정적 변수가 선언 된 블록으로 제한됩니다. 결과적으로 각 프로세스에는 기본적으로 DLL 전역 변수와 정적 변수의 자체 인스턴스가 있습니다.
그리고 여기에서 :
모듈을 동적으로 링크 할 때 다른 라이브러리에 자체 글로벌 인스턴스가 있는지 또는 글로벌 공유 여부가 확실하지 않습니다.
감사합니다.
이것은 Windows와 Unix 계열 시스템의 매우 유명한 차이점입니다.
무슨 일이 있어도 :
- 각 프로세스 에는 자체 주소 공간이 있으므로 프로세스 간 통신 라이브러리 또는 확장을 사용하지 않는 한 프로세스간에 공유되는 메모리가 없습니다.
- 하나의 정의 규칙 (ODR)은 여전히 만 링크시 (정 동적 링크)에서 볼 수적 전역 변수 중 하나를 정의하거나 수있는 것이 의미 적용됩니다.
여기서 중요한 문제는 실제로 가시성 입니다.
모든 경우에 static
외부 변수 (또는 함수)는 모듈 (dll / so 또는 실행 파일)에서 절대 표시되지 않습니다. C ++ 표준에서는 내부 링크가 있어야합니다. 즉, 정의 된 변환 단위 (오브젝트 파일이 됨) 외부에서는 볼 수 없습니다. 그래서 그것은 그 문제를 해결합니다.
복잡한 곳은 extern
전역 변수 가있을 때 입니다. 여기서 Windows와 Unix 계열 시스템은 여기서 처리됩니다.
Windows (.exe 및 .dll)의 경우 extern
전역 변수는 내 소유의 일부가 아닙니다. 즉, 다른 모듈은 다른 모듈에 정의 된 전역 변수를 전혀 인식하지 못합니다. 이는 extern
허용되지 않기 때문에 DLL 정의 된 변수에 를 사용해야하는 실행 파일을 만들려고하는 등의 경우 링커 오류가 발생 함을 의미합니다 . extern 변수의 정의를 오브젝트 파일 (또는 정적 라이브러리)에 제공 하고이를 실행 파일과 DLL 둘 다에 정적으로 링크 하여 두 개의 고유 한 전역 변수 (하나는 실행 파일에 속하고 하나는 DLL에 속함)를 생성해야합니다. 합니다. ).
실제로 Windows에서 전역 변수를 연습하려면 함수 내보내기 / 가져 오기 구문과 추천 구문을 사용합니다.
#ifdef COMPILING_THE_DLL
#define MY_DLL_EXPORT extern "C" __declspec(dllexport)
#else
#define MY_DLL_EXPORT extern "C" __declspec(dllimport)
#endif
MY_DLL_EXPORT int my_global;
그렇게하면 전역 변수가 내 모든 함수와 목록에 추가되고 다른 모든 함수와 같이 링크 될 수 있습니다.
Linux와 같은 Unix와 같은 환경의 경우 확장명을 가진 "공유 객체"라고하는 동적 라이브러리는 .so
모든 extern
전역 변수 (또는 함수)를 내 보냅니다 . 이 경우 어디서나 공유 객체에 로드 타임 링크 를 수행 하면 전역 변수가 공유됩니다. 즉, 하나로 연결됩니다. 기본적으로 유닉스 계열 시스템은 정적 라이브러리 또는 동적 라이브러리와의 링크 사이에 어떤 차이가 완벽 설계되었습니다. 다시 ODR은 보드 전체에 적용됩니다. extern
전역 변수는 모듈에서 공유로드 된 모든 모듈에서 하나의 정의 만 가져옵니다.
마지막으로 두 경우 모두 Windows 또는 Unix 계열 시스템 의 경우 동적 라이브러리의 실행 링크를 수행 할 수 있습니다 ( 예 : LoadLibrary()
/ GetProcAddress()
/ FreeLibrary()
또는 dlopen()
/ dlsym()
/) dlclose()
. 이 경우 사용하려는 각 기호에 대한 포인터를 수동으로 가져와야하며 여기에 사용하려는 전역 변수가 포함됩니다. 전역 변수의 경우, 사용할 수 있습니다 GetProcAddress()
또는 dlsym()
전역 변수 (이전 단락의 규칙에 의해) 내 보낸 기호 목록의 일부임을 제공, 기능처럼 똑같이.
물론 필요한 최종 참고 사항으로 전역 변수는 피해야 합니다. 그리고 당신이 인용 한 ( "불명확 한 것"에 대해)가 근처에 플랫폼 별입니다 텍스트 정확하게 참조 믿습니다 (동적 라이브러리는 실제로 C ++ 표준에 의해 정의되지 않았습니다. 는 /
'IT' 카테고리의 다른 글
Node.js에 대한 자연스러운 함수 작성 방법 (0) | 2020.07.28 |
---|---|
상태 표시 줄이 캐시 된 시간이 없습니다. (0) | 2020.07.28 |
Entity Framework Code First는 저장 프로 시저를 지원합니까? (0) | 2020.07.27 |
정적 인덱서? (0) | 2020.07.27 |
Linux에서 여러 가지로 신호 처리 (0) | 2020.07.27 |