이것은 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;
그렇게하면 전역 변수가 내 보낸 심볼 목록에 추가되고 다른 모든 기능과 마찬가지로 링크 될 수 있습니다.
Unix와 유사한 환경 (Linux와 같은)의 경우 확장이있는 "공유 객체"라고하는 동적 라이브러리는 .so
모든 extern
전역 변수 (또는 함수)를 내 보냅니다 . 이 경우 어디에서나 공유 객체 파일로 로드 타임 링크 를 수행 하면 전역 변수가 공유됩니다. 즉, 하나로 함께 링크됩니다. 기본적으로 유닉스 계열 시스템은 정적 라이브러리와 동적 라이브러리와의 링크 사이에 사실상 차이가 없도록 설계되었습니다. 다시 말하지만, ODR은 보드 전체에 적용됩니다. extern
전역 변수는 모듈간에 공유됩니다. 즉,로드 된 모든 모듈에 대해 하나의 정의 만 있어야합니다.
마지막으로 두 경우 모두 Windows 또는 Unix 계열 시스템의 경우 / / 또는 / / 중 하나를 사용하여 동적 라이브러리의 런타임 링크를 수행 할 수 있습니다 . 이 경우 사용하려는 각 기호에 대한 포인터를 수동으로 가져와야하며 여기에는 사용하려는 전역 변수가 포함됩니다. 전역 변수의 경우 전역 변수가 내 보낸 기호 목록의 일부인 경우 (이전 단락의 규칙에 따라) 함수에 대해 수행하는 것과 동일 하거나 사용할 수 있습니다 .LoadLibrary()
GetProcAddress()
FreeLibrary()
dlopen()
dlsym()
dlclose()
GetProcAddress()
dlsym()
그리고 물론 필요한 마지막 참고 사항으로 전역 변수는 피해야 합니다. 그리고 당신이 인용 한 텍스트 ( "불분명 한 것"에 대해)는 방금 설명한 플랫폼 별 차이점을 정확히 언급한다고 믿습니다 (동적 라이브러리는 실제로 C ++ 표준에 의해 정의되지 않습니다. 이것은 플랫폼 별 영역입니다. 훨씬 덜 신뢰성 / 휴대 성).