C 정적 라이브러리는 눈살을 찌푸리고 있습니까? [닫은]


11

공유 라이브러리를 갖는 데에는 두 가지 인수가 있습니다.

  1. 디스크 공간을 줄이는 데 도움이됩니다.
  2. 공유 라이브러리가 업데이트되면 이에 따라 모든 바이너리가 업데이트됩니다.

공유 라이브러리에는 주로 한 가지 단점이 있습니다.

  • 그들은 의존성 지옥을 소개 할 수있다.

데스크톱 컴퓨터에서 첫 번째 장점은 더 이상 유지되지 않습니다. 요즘 디스크 공간 낭비는 그리 큰 문제가되지 않습니다.

정적 바이너리를 사용하면 더 나은 패키지 관리자를 얻을 수 있습니다. 즉, 종속성 지옥은 과거의 일이 될 것입니다. 프로그램을 추가하는 것은 바이너리를 추가하는 것입니다. 결국 파일을 처리 할 수있는 폴더입니다. 프로그램을 삭제하면이 파일 만 삭제됩니다. 의존성? 지나간.

두 번째 이점은 여전히 ​​유효하지만 데스크톱 컴퓨터에서 정적 바이너리의 이점이 그보다 중요하다고 생각합니다. Go와 같은 새로운 언어조차도 편의 때문에 공유 라이브러리의 장점에도 불구하고 모든 바이너리를 컴파일합니다.


공유 라이브러리의 주요 장점 중 하나는 더 이상 큰 문제가 아니기 때문에 C 정적 라이브러리가 여전히 눈에 띄지 않습니까? 그렇다면 왜 그렇습니까?


4
C가 더 이상 사용되는 주된 이유는 특히 최신 데스크톱 컴퓨터에서 작업 하지 않기 때문 입니다.
Telastyn

18
@Telastyn 죄송합니다? 데스크탑 컴퓨터에 설치된 대부분의 소프트웨어는 C로 작성되었습니다.
Florian Margaine

6
사이드 비트-주제에 대한 오프 사이트 읽기- 동적 연결이 유해한 것으로 간주 됨

6
동적 라이브러리의 장점 중 하나는 15 년 된 폐쇄 소스 게임에서 업데이트 수신이 중단 된 버그, 보안 허점 또는 하드웨어 문제를 해결하기 위해 라이브러리를 업데이트 할 수 있다는 것입니다. 틈새 사례의 종류이지만 좋은 게임은 필수품이 아니기 때문에 "다른 프로그램 만 사용"하면 실제로 도움이되지 않습니다. 또한 자신의 코드를 공개적으로 소싱하지 않고 LGPL을 준수해야합니다.
Doval

4
공유 라이브러리의 다른 두 가지 장점을 잊어 버렸습니다 .1) 메모리에서도 공유됩니다 .2) 모든 링커가 심하게 빨라서 큰 바이너리를 연결하는 것은 매우 불쾌합니다. 바이너리를 여러 개의 작은 엔티티로 나누면 전체 프로세스가 훨씬 더 견딜 수 있습니다.
SK-logic

답변:


9

귀하의 질문의 전제가 잘못되었습니다. 눈살을 찌푸리는 것은 그 뒤에 기초를 이해하지 못하는 교리와 절대에 충실합니다 (Cargo Cult Programming?).

연결된 SO 답변 은 매우 흥미로운 주제입니다-질문은 -static 옵션으로 컴파일이 작동하지 않는 이유에 관한 것입니다. 링크 된 답변은 정적 링크를 사용하지 않는 것에 대한 열망에 지나지 않습니다. 왜 나쁜지에 대해 논의하지 않고 OP는 동적 링크를 사용합니다. 불행히도 정답으로 표시됩니다 (다음 답변은 두 배의 투표권을 가지며 OP 질문에 대한 정답입니다). 정답은 있지만 교의 적 의견 사이에 깊이 숨겨져 있기 때문입니다.

실제 문제는 정적 링크와 동적 링크의 장단점이 무엇이며 언제 다른 링크보다 선호 되는가입니다.


2
바 실레의 대답은 하지 않습니다 당신에게 정확하게 왜 공유 라이브러리를 사용하는 것이 좋습니다 : ? "당신이 링크를 정적으로 응용 프로그램을 원하는 이유는 무엇입니까 . (당신이 시스템의 동적 라이브러리에 대한 업데이트에서 이익을하지 않기 때문에) 그것은 실수가 일반적으로 특정 이름 서비스 스위치에서 libc의에서 시설은 동적 라이브러리를 원한다. " 그것은하지"당신은 그것으로 호언 장담을 "동의해서.
코디 그레이

@Cody 내가 그것을 rant라고 부른 이후로 연결된 답변이 편집되었습니다. 정적 연결과 동적 연결에 대해 내가 생각하는 유일한 견해는 여러분의 필요에 맞는 것을 사용하고 선택의 강점과 약점을 이해하는 것이 아니라 "누군가가 그렇게 말했기 때문에"화물 컬트 프로그래밍 교리에 빠지는 것입니다.
mattnz

네, "특히 ..."부분이 추가되었습니다. 그것이 그 rant 상태에 어떤 영향을 미치는지 확실하지 않습니다. 물론 나는화물 컬트 프로그래밍을 옹호하지 않습니다. 정적 연결 (제 경험상) 지지자들이 종종 보안 문제를 놓치거나 과소 평가하는 것입니다. 정적 링크는 일회성 유틸리티에 매우 적합하므로 앱이 자체 포함되어 배포가 훨씬 쉬워집니다. 그러나 프로덕션에 널리 배포되거나 사용될 앱은 실제로 공유 라이브러리에 연결되어야합니다. 실제 단점은 없습니다.이 수준의 앱에는 이미 배포 프로세스가 필요합니다.
Cody Grey

1
정적 연결이 적합한 곳의 좋은 예는 내가 작업하는 곳입니다. 크고 복잡한 생명에 중요한 시스템입니다. 중요한 모듈을 테스트하고 작동 승인을 받으면 '프로세스'를 거치지 않고 동작이 변경되어서는 안됩니다. 그러나 시스템의 운영 및 수명에 중요하지 않은 부분 (청구 및보고)은 덜 강력한 제어가 필요하지 않으며 동적 연결을 사용하지 않습니다.
mattnz

7

개발자의 관점에서 동적 링크는 종종 컴파일 / 링크 / 테스트 루프 속도를 크게 높일 수 있습니다.

패키지 관리 관점에서 libGL을 예로들 수 있습니다. 패키지 관리자에서 사용할 수있는 대략 12 가지의 구현이 있으며 일부는 특정 그래픽 카드를 대상으로합니다. 동적으로 연결되어 있지 않다면 libGL과 연결되는 각 프로그램의 12 가지 버전이 있어야합니다. 그렇지 않으면 함수 호출만큼 효율적이지 않은 추가 추상화 계층을 고안해야합니다.

Qt와 같은 인기있는 라이브러리의 보안 문제를 생각해보십시오. 동적 연결을 사용하면 Qt에 연결된 모든 단일 패키지를 식별, 재 컴파일 및 배포하는 대신 해당 패키지 하나만 업데이트 할 수 있습니다.

정적 링크는 독립적으로 배포 된 폐쇄 형 소스 응용 프로그램에서 이점을 가질 수 있지만 오픈 소스 패키지 관리에서는 도움이되는 것보다 더 많은 문제가 있습니다.


2
이것은 사실이지만 (개발 속도를 높이는 것이지만) 프로덕션 환경으로 만드는 것은 정말 실망 스럽습니다. 일반적인 예는 Firefox입니다. 합리적인 시간에 Firefox가로드되도록 동적 링크 심볼 분석 속도를 높이는 데 필요한 엔지니어링 노력 (끔찍한 해킹 형태)의 양은 완전히 미쳤습니다. 프로젝트 내 모든 코드를 정적 링크하려는 경우 (원하는 경우 여전히 동적 링크 시스템 라이브러리 및 플러그인) 엔지니어링 비용을 줄이면 훨씬 더 나은 성능을 얻을 수 있습니다.
R .. GitHub 중지 지원 얼음

5

공유 라이브러리는 기본적으로 Linux 배포판 관리자가 선호하는 이유 # 2입니다. 예를 들어, 누군가 zlib에서 보안 버그를 발견하면 zlib 를 사용하는 모든 프로그램 중 하나를 다시 컴파일 할 필요가 없다는 점은 매우 중요 합니다. 다시 컴파일하면 배포판을 사용하는 모든 사람 이 해당 프로그램을 모두 다시 다운로드 해야합니다. 한편, 배포판에서 제공하는 패키지 세트 내에서 모든 것이 해당 라이브러리 세트에서 작동하도록 테스트 되었기 때문에 종속성 지옥은 문제가되지 않습니다.

배포판에없는 라이브러리가 필요한 타사 소프트웨어를 구축하는 경우 해당 라이브러리 를 정적으로 연결 하는 것이 대안보다 덜 번거로울 수 있습니다.

알아야 할 또 다른 중요한 점은 GNU libc와 GCC libstdc++모두 라이브러리가 정적으로 링크 된 경우 안정적으로 작동하지 않는 구성 요소를 가지고 있다는 것입니다. 가장 일반적인 문제는 함께 dlopen당신이로드 모듈 무엇 때문에, dlopen그 자체가되어 동적 으로 연결 libc.so.6. 따라서 이제는 주소 공간에 두 개의 C 라이브러리 사본이 있으며 내부 malloc데이터 구조의 사본 (예 : 권위있는)에 대해 동의하지 않을 경우에 문제가 발생합니다 . 그것은 악화 : 표시되지 않는 기능의 모두가 함께 할 수있는 아무것도 가지고 dlopen, 같은 gethostbynameiconv, 사용dlopen내부적으로 (동작이 런타임 구성 가능하도록) 다행히도 libc 및 libstdc ++ 용 ABI는 매우 안정적이므로 동적으로 연결하는 데 문제가 발생하지 않습니다.


2

mattnz의 마지막 요점에 동의합니다.이 질문은로드 된 질문입니다. 정적 연결이 잘못되었다고 가정합니다. 이것이 사실이 아닌 두 가지 이유를 생각할 수 있습니다.

  • 정적 연결은 안전합니다. 공유 라이브러리가 업데이트되어 응용 프로그램이 새 라이브러리를 사용하도록 (새 라이브러리가 기존 라이브러리를 덮어 쓰거나 이전 라이브러리를 제거 할 수 있음) 새 버전이 응용 프로그램을 손상시킬 위험이 있습니다. 이것은 응용 프로그램의 공식 업데이트 범위를 벗어난 코드 변경입니다. 테스트되지 않았을 수 있습니다. 정적 링크는 외부에서 라이브러리를 공유하지 않음으로써이를 회피합니다. 이 위험으로 인해 공유 라이브러리 에는 이것이 단점 이라고 생각합니다 . 공유 라이브러리의 새 버전에 특정 이전 응용 프로그램을 손상시키는 새로운 버그가 도입되면 어떻게됩니까?

  • 정적 연결을 통해 응용 프로그램을보다 독립적으로 유지할 수 있습니다. 공유 라이브러리는 기본 실행 파일과 함께 배치 될 수 있지만 종종 공유 위치에 저장됩니다. 정적으로 링크 된 응용 프로그램은 "OS가 소유 한 파일, 디렉토리 또는 설정을 변경할 필요가 없음"(Windows 디렉토리, 레지스트리, / etc 등)에 대한 의미로 "휴대용"을 보장하기가 더 쉽습니다.


내가 언급하려는 장점을 개선해 주셔서 감사합니다. 그러나 예를 들어 Linux 배포판에서 제공하는 대부분의 패키지는 정적으로 컴파일되지 않습니다. 그것은 않는 정적 컴파일이 적어도보기의 외부 관점에서, 눈살을 찌푸리게한다 보인다.
Florian Margaine

1
요즘 거의 모든 OS의 동적 라이브러리는 수요에 따라 페이징됩니다. 실제로 사용중인 페이지 만 메모리에 있습니다. 여러 애플리케이션이 동일한 기능을 사용하는 경우 메모리를 공유하고 정적 라이브러리 케이스보다 적게 사용합니다. 동일한 라이브러리에서 여러 앱이 서로 다른 기능을 사용하는 경우 두 기능 세트가 모두 페이징되어 정적 접근 방식과 거의 동일한 영향을 미칩니다.
Alan Shutko

@ AlanShutko 나는 당신이 언급 한 것 때문에 그 부분을 여러 가지 방법으로 고투하고 재 입력했습니다. 최신 운영 체제가 실제로 정적 오버 헤드로 공유 라이브러리의 효율성을 제공하더라도 실제 보장은 없습니다. 다시 편집하겠습니다.

@ Snowman 나는 기본 포인트는 동적 링크를 제공하는 현실적인 운영 체제 (동적 링크를 사용하지만 페이징을 요구하지 않는 OS는 모른다)의 두 번째 포인트가 물을 보유하지 않는다는 것입니다. 메모리는 실제로 사용되지 않습니다 함수를 사용하지 않고 동적 라이브러리에서 사용하는 메모리를 사용하여 다른 프로그램간에 공유 할 수 있으므로 동적 버전의 메모리 사용이 덜 효율적입니다. 첫 번째와 세 번째 이유는 유효하지만 두 번째 이유는 단순히 삭제합니다. 현실적인 가정에서는 잘못된 것입니다.
Jules

@Jules 나는 현대 운영 체제에서 문제가되고 모호한 타당성을 지적했다. 나는 그것을 제거했다.

1

정적 및 동적 라이브러리는 각각 자체 용도로 사용됩니다. 범위 내에서 단일 응용 프로그램을 보면 필요한 것과 그렇지 않은 것에 대해 다른 아이디어를 얻습니다.

정적 연결은 응용 프로그램 배포를 대폭 간소화합니다. 다른 버전을 감지하고 처리 할 필요가 없습니다. 굽고 배포하기 만하면됩니다.

동적 라이브러리의 장점은 업데이트를 독립적으로 적용 할 수 있다는 것입니다.

이것이 내가 maven과 다른 유사한 동적 링크 프로젝트 빌더를 java에 싫어하는 이유 중 하나입니다. 그들은 주어진 URL에서 영원히 단일 라이브러리 버전을 사용할 수있을 것으로 기대합니다. 모든 소스와 항아리가 없어서 아무도 응용 프로그램을 컴파일 할 수 없을 때 10 년 동안 발생하는 문제를 이해하지 못합니다.


FooLib1.8함께 제공되는 업그레이드 유틸리티를 사용 FooLib1.9하여 업그레이드 또는 다운 그레이드 할 수 있도록 해당 라이브러리에 대한 코드를 실행 패키지에 표준 방식으로 포함 할 수 없는 특정 이유 가 있습니까? 코드가 클래식 매킨토시에 저장되어있는 방식은 그렇게 쉽게 만들었습니다. 오늘날의 시스템이 더 나아질 수없는 이유가 있습니까?
supercat

@ supercat 당신은 주어진 라이브러리의 모든 버전이 시스템에서 사용 가능하다는 것을 의미합니까? 질문을 이해하지 못했습니다. OP 질문은 함께 패키징되는 정적 라이브러리 대 시스템 전체 공유 라이브러리에 대한 것이 었습니다.
많은 파삭 파삭

내 요점은 실행 가능한 패키지가 포함되어있는 라이브러리를 업그레이드 할 가능성을 배제 할 필요가없는 모든 라이브러리를 포함한다는 것입니다. 따라서 배포 후 사물을 업그레이드하는 기능을 응용 프로그램과 라이브러리와 함께 제공하지 않는 이점으로 간주한다는 것을 알지 못합니다.
supercat

주어진 라이브러리의 라이센스로 패키지와 함께 배포 할 수 있다면 항상 선호하는 방법입니다. 외부 종속성의 수를 줄입니다. 모든 것을 배포 할 것이기 때문에 업그레이드 또는 패치 메커니즘은 정적 또는 동적으로 동일한 방식으로 작동합니다. 패치는 일반적으로 이진 델타를 기반으로합니다. 차이가 없습니다.
많은 파삭 파삭
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.