문제

우선 가비지 컬렉션의 장점 때문에 이런 질문을 하는 것은 아닙니다.내가 이것을 묻는 주된 이유는 Bjarne Stroustrup이 C++가 어느 시점에는 가비지 수집기를 갖게 될 것이라고 말했다는 것을 알고 있기 때문입니다.

그런데 왜 추가되지 않았나요?이미 C++용 가비지 수집기가 있습니다.이것은 단지 "말로는 실천하기 쉬운" 유형의 일 중 하나에 불과합니까?아니면 추가되지 않은(C++11에는 추가되지 않는) 다른 이유가 있나요?

상호 링크:

명확히 하기 위해 C++이 처음 생성되었을 때 가비지 수집기가 없었던 이유를 이해합니다.왜 컬렉터를 추가할 수 없는지 궁금합니다.

도움이 되었습니까?

해결책

암시 적 쓰레기 수집이 추가 될 수 있었지만 단지 컷을 만들지 않았습니다. 아마도 구현 합병증뿐만 아니라 사람들이 일반적인 합의에 충분히 빨리 올 수 없기 때문일 것입니다.

Bjarne Stroustrup 자신의 인용문 :

선택적으로 활성화 될 수있는 쓰레기 수집가가 C ++ 0x의 일부가되기를 바랐지만 그러한 수집가가 나머지 언어와 어떻게 통합되는지에 대한 자세한 사양으로해야 할 충분한 기술적 문제가있었습니다. 제공된 경우. 본질적으로 모든 C ++ 0X 기능의 경우와 마찬가지로 실험적 구현이 존재합니다.

주제에 대한 좋은 토론이 있습니다 여기.

일반 개요 :

C ++는 매우 강력하며 거의 모든 것을 할 수 있습니다. 이러한 이유로 성능에 영향을 줄 수있는 많은 것들을 자동으로 푸시하지 않습니다. 스마트 포인터 (참조 수로 포인터를 감싸는 개체, 참조 수가 0에 도달 할 때 자동 삭제하는 개체)로 쓰레기 수집을 쉽게 구현할 수 있습니다.

C ++는 쓰레기 수집이없는 경쟁사를 염두에두고 구축되었습니다. 효율성은 C ++가 C 및 다른 사람들에 비해 비판을 막아야한다는 주요 관심사였습니다.

쓰레기 수집에는 두 가지 유형이 있습니다 ...

명백한 쓰레기 수집 :

C ++ 0X는 shared_ptr로 생성 된 포인터를 통해 쓰레기 수집이 있습니다.

당신이 그것을 원한다면 그것을 사용할 수 있습니다. 원하지 않으면 그것을 사용하도록 강요받지 않습니다.

C ++ 0x를 기다리지 않으려면 현재 Boost : Shared_ptr을 사용할 수 있습니다.

암시 적 쓰레기 수집 :

그래도 투명한 쓰레기 수거는 없습니다. 그러나 향후 C ++ 사양의 초점이 될 것입니다.

TR1이 암시 적 쓰레기 수집이없는 이유는 무엇입니까?

C ++ 0X의 TR1이 가지고 있어야했던 많은 것들이 있습니다. Bjarne Stroustrup은 이전 인터뷰에서 TR1이 그가 좋아했던 것만 큼 많지 않았다고 말했습니다.

다른 팁

여기에 토론을 추가합니다.

가비지 수집에는 알려진 문제가 있으며 이를 이해하면 C++에 가비지 수집이 없는 이유를 이해하는 데 도움이 됩니다.

1.성능 ?

첫 번째 불만은 종종 성능에 관한 것이지만 대부분의 사람들은 자신이 말하는 내용을 실제로 깨닫지 못합니다.설명된 바와 같이 Martin Beckett 문제는 성능 자체가 아니라 성능 예측 가능성일 수 있습니다.

현재 널리 배포되는 2가지 GC 제품군이 있습니다.

  • Mark-And-Sweep 종류
  • 참조-카운팅 종류

그만큼 Mark And Sweep 속도는 더 빠르지만(전체 성능에 미치는 영향은 적음) "세계 동결" 현상이 발생합니다.즉, GC가 시작되면 GC가 정리할 때까지 다른 모든 작업이 중지됩니다.몇 밀리초 안에 응답하는 서버를 구축하고 싶다면...일부 거래는 귀하의 기대에 부응하지 못할 수도 있습니다 :)

문제는 Reference Counting 은 다르다:참조 카운팅은 원자 카운트가 필요하기 때문에 특히 멀티스레딩 환경에서 오버헤드를 추가합니다.또한 참조 순환 문제가 있으므로 해당 순환을 감지하고 제거하려면 영리한 알고리즘이 필요합니다(일반적으로 빈도는 낮지만 "세계 동결"을 통해 구현함).일반적으로 현재로서는 이 종류(일반적으로 반응성이 더 높거나 정지 빈도가 낮더라도)는 다음 유형의 것보다 느립니다. Mark And Sweep.

나는 에펠탑 구현자들이 작성한 논문을 보았습니다. Reference Counting 글로벌 성능이 비슷한 가비지 컬렉터 Mark And Sweep "Freeze The World" 측면이 없습니다.GC(일반)에는 별도의 스레드가 필요했습니다.알고리즘은 (결국) 약간 무서웠지만 이 논문은 개념을 한 번에 하나씩 소개하고 알고리즘이 "간단한" 버전에서 본격적인 버전으로 진화하는 모습을 잘 보여주었습니다.PDF 파일에 다시 손을 얹을 수만 있다면 읽어 보는 것이 좋습니다...

2.자원 획득은 초기화입니다

에서 흔히 쓰이는 관용구에요 C++ 리소스의 소유권을 개체 내에서 래핑하여 리소스가 올바르게 해제되도록 해야 합니다.가비지 수집이 없기 때문에 주로 메모리에 사용되지만 그럼에도 불구하고 다른 많은 상황에도 유용합니다.

  • 잠금(다중 스레드, 파일 핸들, ...)
  • 연결(데이터베이스, 다른 서버, ...)

아이디어는 객체의 수명을 적절하게 제어하는 ​​것입니다.

  • 당신이 필요로 하는 한 그것은 살아 있어야 합니다
  • 다 끝나면 죽여야 해

GC의 문제는 전자에 도움이 되고 나중에는 궁극적으로 보장된다면...이 "궁극적"만으로는 충분하지 않을 수 있습니다.잠금을 해제하면 지금 해제하여 더 이상 통화를 차단하지 않는 것이 좋습니다!

GC가 있는 언어에는 두 가지 해결 방법이 있습니다.

  • 스택 할당이 충분할 때는 GC를 사용하지 마세요.일반적으로 성능 문제에 대한 것이지만 우리의 경우에는 범위가 수명을 정의하므로 정말 도움이 됩니다.
  • using 건설하다...하지만 명시적(약한) RAII인 반면 C++에서는 RAII가 암시적이므로 사용자가 무의식적으로 오류를 범할 수 없습니다( using 예어)

삼.스마트 포인터

스마트 포인터는 종종 메모리를 처리하는 묘책으로 나타납니다. C++.나는 종종 다음과 같은 말을 들었습니다.스마트 포인터가 있기 때문에 결국 GC가 필요하지 않습니다.

더 이상 틀릴 수는 없습니다.

스마트 포인터가 도움이 됩니다: auto_ptr 그리고 unique_ptr RAII 개념을 사용하면 실제로 매우 유용합니다.너무 간단해서 혼자서도 아주 쉽게 작성할 수 있습니다.

그러나 소유권을 공유해야 하는 경우에는 더 어려워집니다.여러 스레드 간에 공유할 수 있으며 카운트 처리에 몇 가지 미묘한 문제가 있습니다.그러므로 사람은 자연스럽게 다음을 향해 나아간다. shared_ptr.

그것은 훌륭합니다. 결국 Boost는 이것이지만 만능은 아닙니다.사실 가장 큰 문제는 shared_ptr 에 의해 구현된 GC를 에뮬레이션한다는 것입니다. Reference Counting 하지만 사이클 감지를 직접 구현해야 합니다...우르그

물론 이런 것도 있어요 weak_ptr 하지만 불행히도 이미 사용에도 불구하고 메모리 누수가 발생했습니다. shared_ptr 그 주기 때문에...멀티 스레드 환경에서는 감지하기가 매우 어렵습니다!

4.해결책은 무엇입니까?

만병통치약은 없지만 언제나 그렇듯이 확실히 가능합니다.GC가 없는 경우 소유권을 명확히 해야 합니다.

  • 가능하다면 특정 시점에 단일 소유자를 갖는 것을 선호합니다.
  • 그렇지 않은 경우 클래스 다이어그램에 소유권과 관련된 주기가 없는지 확인하고 weak_ptr

그렇다면 실제로 GC가 있으면 정말 좋을 것 같습니다.그러나 그것은 사소한 문제가 아닙니다.그리고 그동안 우리는 소매를 걷어붙이면 됩니다.

어떤 유형? 임베디드 세탁기 컨트롤러, 휴대 전화, 워크 스테이션 또는 슈퍼 컴퓨터에 최적화되어야합니까?
GUI 응답 성 또는 서버로드의 우선 순위를 정해야합니까?
많은 메모리 나 CPU를 많이 사용해야합니까?

C/C ++는 너무 많은 상황에서 사용됩니다. Boost Smart Pointers와 같은 것이 대부분의 사용자에게 충분할 것 같습니다.

편집 - 자동 쓰레기 수집기는 성능 문제가 많지 않습니다 (항상 더 많은 서버를 구입할 수 있음) 예측 성능의 문제입니다.
GC가 언제 시작될시기를 알지 못하는 것은 마약 항공사 조종사를 사용하는 것과 같습니다. 대부분은 대단합니다. 그러나 실제로 반응이 필요할 때!

C ++가 쓰레기 수집에 내장되지 않은 가장 큰 이유 중 하나는 쓰레기 수집을 파괴자와 잘 어울리는 것이 정말 어렵 기 때문입니다. 내가 아는 한, 아무도 아직 완전히 해결하는 방법을 아무도 모른다. 처리해야 할 많은 문제가 있습니다.

  • 물체의 결정 론적 수명 (참조 계산은 당신에게 이것을 제공하지만 GC는 그렇지 않습니다. 비록 그렇게 큰 거래는 아닐 수도 있습니다).
  • 물체가 쓰레기를 수집 할 때 파괴자가 던지면 어떻게됩니까? 대부분의 언어는이 예외를 무시할 수 있습니다. 왜냐하면 그것을 전송할 수있는 캐치 블록이 없기 때문에 C ++에게는 허용되는 솔루션이 아닐 것입니다.
  • 활성화/비활성화하는 방법은 무엇입니까? 당연히 컴파일 타임 결정 일 것입니다. 그러나 GC가 아닌 GC 대 코드를 위해 작성된 코드는 매우 다르고 호환되지 않을 것입니다. 이것을 어떻게 조정합니까?

이것들은 직면 한 몇 가지 문제 일뿐입니다.

이것은이지만 낡은 질문, 여전히 아무도 언급 한 사람이 전혀없는 한 가지 문제가 있습니다. 가비지 컬렉션은 지정하기가 거의 불가능합니다.

특히, C ++ 표준은 구현이 해당 동작을 달성하는 방법보다는 외부 관찰 가능한 동작 측면에서 언어를 지정하는 데 매우 신중합니다. 그러나 쓰레기 수거의 경우 ~이다 사실상 외부 관찰 가능한 행동이 없습니다.

그만큼 일반적인 생각 쓰레기 수집은 메모리 할당이 성공할 수 있도록 합리적인 시도를해야한다는 것입니다. 불행히도, 쓰레기 수집가가 작동하더라도 메모리 할당이 성공할 것을 보장하는 것은 본질적으로 불가능합니다. 이것은 어쨌든 어느 정도는 사실이지만, 특히 C ++의 경우에는 수집주기 동안 메모리의 객체를 메모리에서 움직이는 복사 수집기 (또는 유사한 것)를 사용할 수 없기 때문에 C ++의 경우 특히 그렇습니다.

객체를 움직일 수 없다면 할당을 할 수있는 단일의 인접한 메모리 공간을 만들 수 없습니다. , 시간이 지남에 따라 조각화됩니다. 이는 요청 된 금액보다 메모리가없는 경우에도 할당이 성공하는 것을 방해 할 수 있습니다.

그것을 생각해내는 것이 가능할 수도 있습니다 약간 (본질적으로) 반복적으로 동일한 패턴을 반복적으로 반복하고 처음으로 성공하면 할당 된 메모리가 반복 사이에 액세스 할 수 없게된다면 후속 반복에서 계속 성공할 것이라고 (본질적으로) 보증합니다. 그것은 본질적으로 쓸모가 없다는 약한 보증이지만, 그것을 강화할 합리적인 희망을 볼 수는 없습니다.

그럼에도 불구하고 C ++에 제안 된 것보다 강합니다. 그만큼 이전 제안 경고 : PDF] (떨어졌다)는 전혀 아무것도 보장하지 않았습니다. 28 페이지의 제안서에서, 당신이 외부 관찰 가능한 행동을 방해하는 것은 단일 (규칙적이지 않은) 메모였습니다.

참고 : 쓰레기 수집 된 프로그램의 경우, 고품질 호스팅 구현은 재생하는 도달 할 수없는 메모리의 양을 최대화하려고 시도해야합니다. - 엔드 참고

적어도 나를 위해, 이것은 a 심각한 투자 수익에 대한 질문. 우리는 기존 코드를 위반할 것입니다 (정확히 얼마나 확실하지만 확실히 확실하지는 않습니다), 구현에 새로운 요구 사항과 코드에 대한 새로운 제한 사항을 배치 할 것입니다.

기껏해야 우리가 얻는 것은 Java로 테스트, 아마도 지금과 같은 속도로 실행하려면 약 6 배의 메모리가 필요할 것입니다. 더 나쁜 것은, 쓰레기 수집은 처음부터 Java의 일부였습니다. 더 나쁜 비용/혜택 비율 (제안서가 보장 한 것을 넘어서 혜택이 있다고 가정하더라도).

나는 수학적으로 상황을 요약했다 : 이것은 복잡한 상황이다. 모든 수학자가 알고 있듯이 복소수에는 실제와 상상의 두 부분이 있습니다. 우리가 여기있는 것은 실제 비용이지만 (적어도 대부분) 상상의 이점 인 것 같습니다.

자동 쓰레기 수집을 원한다면 C ++를위한 우수한 상업용 및 공공 도메인 쓰레기 수집가가 있습니다. 쓰레기 수집이 적합한 응용 분야의 경우 C ++는 다른 쓰레기 수집 언어와 호의적으로 비교되는 성능을 가진 우수한 쓰레기 수집 언어입니다. 보다 C ++ 프로그래밍 언어 (4 판) C ++의 자동 쓰레기 수집에 대한 논의. Hans-J 참조. Boehm 's C 및 C ++ 쓰레기 수집 사이트 (보관소).

또한 C ++는 메모리 관리가 될 수있는 프로그래밍 기술을 지원합니다. 쓰레기 수집가가없는 안전하고 암시 적. 나는 쓰레기 수집을 마지막 선택과 자원 관리를위한 불완전한 처리 방법이라고 생각합니다. 그렇다고해서 유용하지 않다는 것을 의미하지는 않습니다. 많은 상황에서 더 나은 접근 방식이 있다는 것을 의미합니다.

원천: http://www.stroustrup.com/bs_faq.html#garbage-collection

왜 그것이 내장되어 있지 않은지에 관해서, 내가 정확하게 기억한다면 GC가 물건, 그리고 나는 언어가 몇 가지 이유로 GC를 가질 수 있다고 생각하지 않습니다 (즉, C와의 거꾸로 양적).

도움이 되었기를 바랍니다.

Stroustrup은 2013 Going Native Conference에서 이것에 대해 좋은 의견을 제시했습니다.

약 25M50을 건너 뛰십시오 이 비디오. (실제로 전체 비디오를 보는 것이 좋습니다. 그러나 이것은 쓰레기 수집에 관한 것들로 건너 뜁니다.)

당신이 정말로 훌륭한 언어를 가지고있을 때, 쉽고 안전하고 예측하기 쉬우 며 읽기 쉬우 며, 어지럽히기 쉽고, 직접적인 방식으로 객체와 값을 처리 할 수있는 (명시 적) 사용을 피할 수 있습니다. 힙, 그럼 당신은조차하지 않습니다 원하다 쓰레기 수집.

현대 C ++와 C ++ 11에있는 물건을 사용하면 제한된 상황을 제외하고 가비지 컬렉션이 더 이상 바람직하지 않습니다. 실제로, 좋은 쓰레기 수집기가 주요 C ++ 컴파일러 중 하나에 내장되어 있더라도 자주 사용되지 않는다고 생각합니다. 그럴 것입니다 더 쉬운, GC를 피하기 위해 더 어렵지 않습니다.

그는이 예를 보여줍니다.

void f(int n, int x) {
    Gadget *p = new Gadget{n};
    if(x<100) throw SomeException{};
    if(x<200) return;
    delete p;
}

이것은 C ++에서 안전하지 않습니다. 그러나 자바에서도 안전하지 않습니다! C ++에서 함수가 일찍 돌아 오면 delete 절대 호출되지 않습니다. 그러나 Java와 같은 완전한 쓰레기 수집을 가지고 있다면, 당신은 단지 "미래의 어느 시점에서"대상이 파괴 될 것이라는 제안을받을뿐입니다.업데이트: 이것보다 더 나쁘다. Java는 그렇습니다 ~ 아니다 Finalizer라고 부를 것을 약속하십시오. 가제트가 열린 파일 핸들 또는 데이터베이스에 대한 연결 또는 나중에 데이터베이스에 쓰기 위해 버퍼링 된 데이터를 보유하는 경우에는 충분하지 않습니다. 우리는 가제트가 완료 되 자마자 파괴되기를 원합니다. 더 이상 필요하지 않은 수천 개의 데이터베이스 연결로 어려움을 겪고있는 데이터베이스 서버를 원하지 않습니다. 프로그램이 완료되었음을 알 수 없습니다.

그래서 해결책은 무엇입니까? 몇 가지 접근 방식이 있습니다. 대부분의 대상에 사용할 수있는 명백한 접근법은 다음과 같습니다.

void f(int n, int x) {
    Gadget p = {n};  // Just leave it on the stack (where it belongs!)
    if(x<100) throw SomeException{};
    if(x<200) return;
}

입력하려면 더 적은 문자가 필요합니다. 가지고 있지 않습니다 new 방해가됩니다. 입력 할 필요는 없습니다 Gadget 두 배. 객체는 함수의 끝에서 파괴됩니다. 이것이 당신이 원하는 것이라면, 이것은 매우 직관적입니다. GadgetS는 동일하게 행동합니다 int 또는 double. 예측 가능하고 읽기 쉬운, 교과성. 모든 것이 '가치'입니다. 때로는 큰 가치이지만, 당신은 당신이 포인터 (또는 참조)로 얻을 수있는 '거리에서'행동이 없기 때문에 가르치기가 더 쉽습니다.

당신이 만드는 대부분의 객체는 생성 된 함수에만 사용되며 아마도 자식 함수에 대한 입력으로 전달 될 수 있습니다. 프로그래머는 객체를 반환 할 때 '메모리 관리'에 대해 생각할 필요가 없거나 소프트웨어의 널리 분리 된 부분에서 객체를 공유 할 필요가 없습니다.

범위와 수명이 중요합니다. 대부분의 경우, 수명이 범위와 동일하다면 더 쉽습니다. 이해하기 쉽고 가르치기가 더 쉽습니다. 다른 수명을 원할 때, 당신이하고있는 코드를 사용하여 shared_ptr 예를 들어. (또는 값으로 반환 (큰) 객체, 이동성 활용 또는 unique_ptr.

이것은 효율성 문제처럼 보일 수 있습니다. 가제트를 반환하고 싶다면 어떻게해야합니까? foo()? C ++ 11의 움직임 의미론으로 인해 큰 물체를 더 쉽게 반환 할 수 있습니다. 그냥 써 Gadget foo() { ... } 그리고 그것은 단지 작동하고 빨리 일할 것입니다. 당신은 엉망이 될 필요가 없습니다 && 자신, 가치로 물건을 돌려 주면 언어는 종종 필요한 최적화를 할 수 있습니다. (C ++ 03 이전에도 컴파일러는 불필요한 복사를 피하는 데 큰 도움이되었습니다.)

Stroustrup이 비디오의 다른 곳에서 말했듯이 (paraphrasing) : "컴퓨터 과학자만이 물체를 복사 한 다음 원본을 파괴 할 것을 주장 할 것입니다. (청중은 웃음). 왜 객체를 새로운 위치로 직접 이동하지 않습니까? 이것이 인간 (컴퓨터 과학자가 아닌)이 기대하는 것입니다."

객체의 사본이 하나만 필요하다는 것을 보장 할 수 있다면 객체의 수명을 이해하는 것이 훨씬 쉽습니다. 원하는 평생 정책을 선택할 수 있으며 원하는 경우 쓰레기 수집이 있습니다. 그러나 다른 접근법의 이점을 이해하면 쓰레기 수집이 선호도 목록의 맨 아래에 있음을 알 수 있습니다.

그것이 당신에게 효과가 없다면, 당신은 사용할 수 있습니다 unique_ptr, 또는 실패, shared_ptr. 잘 쓰여진 C ++ 11은 메모리 관리와 관련하여 다른 많은 언어보다 짧고 읽기 쉬우 며 접수하기 쉽습니다.

C ++의 배후에있는 아이디어는 사용하지 않는 기능에 대해 성능 영향을 지불하지 않는다는 것입니다. 따라서 쓰레기 수집을 추가하면 일부 프로그램이 C가 수행하는 방식과 일부 런타임 가상 머신 내에서 일부 프로그램이 하드웨어에서 직접 실행되는 것을 의미했습니다.

타사 쓰레기 수집 메커니즘에 묶인 어떤 형태의 스마트 포인터를 사용하지 못하게하는 것은 없습니다. 나는 Microsoft가 COM과 같은 일을하는 것을 기억하는 것 같습니다.

C ++에 대한 대부분의 "왜"질문에 대답하려면, 읽으십시오. C ++의 설계 및 진화

현대 C ++는 쓰레기 수집이 필요하지 않기 때문입니다.

Bjarne Stroustrup의 FAQ 이 문제에 대한 답변은 말합니다:

나는 쓰레기를 좋아하지 않는다. 나는 쓰레기를 좋아하지 않는다. 저의 이상은 쓰레기를 생산하지 않음으로써 쓰레기 수집가의 필요성을 제거하는 것입니다. 이제 가능합니다.


요즘 작성된 코드의 상황 (C ++ 17 및 공무원 핵심 지침) 다음과 같다:

  • 대부분의 메모리 소유권 관련 코드는 라이브러리 (특히 컨테이너를 제공하는 코드)에 있습니다.
  • 대부분 사용 메모리 소유권과 관련된 코드는 RAII를 따릅니다 무늬, 따라서 파괴에 대한 건설 및 거래에 대한 할당이 이루어지며, 무언가가 할당 된 범위를 종료 할 때 발생합니다.
  • 메모리를 직접 명시 적으로 할당하거나 처리하지 마십시오.
  • 원시 포인터 기억을 소유하지 마십시오 (가이드 라인을 따랐다면), 당신은 그들을 지나쳐 누출 할 수 없습니다.
  • 메모리에서 일련의 값 시퀀스 주소를 어떻게 전달할 것인지 궁금하다면 기간; 원시 포인터가 필요하지 않습니다.
  • 실제로 "포인터"가 필요하다면 C ++를 사용합니다. 표준 라이브러리 스마트 포인터 - 누출 할 수없고 매우 효율적입니다. 또는 스코프 경계에 걸쳐 소유권을 전달할 수 있습니다. "소유자 포인터". 이것들은 드문 일이며 명시 적으로 사용되어야합니다. 그리고 그들은 누출에 대한 부분 정적 점검을 허용합니다.

"오 예?하지만 어때요 ...

... 단지 코드를 작성하면 옛날에 C ++를 쓰는 데 사용한 방식입니까? "

사실, 당신 ~할 수 있었다 모든 지침을 무시하고 유출 된 응용 프로그램 코드를 작성하면 항상 마찬가지로 컴파일 및 실행 (및 누출)을 작성합니다.

그러나 개발자가 덕이되고 많은 자기 통제를 행사할 것으로 예상되는 "그냥 그렇게하지 않는"상황이 아닙니다. 부적합한 코드를 작성하는 것은 간단하지 않으며 글을 쓰는 것이 더 빠르거나 더 잘 수행되지도 않습니다. 점차적으로 코드가 제공하고 기대하는 것과 함께 증가하는 "임피던스 불일치"에 직면하므로 글을 쓰기가 더 어려워 질 것입니다.

... 만약 내가 reintrepret_cast? 아니면 포인터 산술이 있습니까? 아니면 다른 해킹? "

실제로, 당신이 당신의 마음을 생각하면, 당신은 가이드 라인을 잘 연주 했음에도 불구하고 물건을 엉망으로 만드는 코드를 작성할 수 있습니다. 하지만:

  1. 당신은 거의하지 않을 것입니다 (코드의 장소에서, 반드시 실행 시간의 일부 일 필요는 없습니다)
  2. 당신은 우연히도 의도적으로 만 이것을 할 것입니다.
  3. 그렇게하는 것은 가이드 라인을 준수하는 코드베이스에서 눈에 띄게됩니다.
  4. 어쨌든 다른 언어로 GC를 우회 할 코드의 종류입니다.

... 도서관 개발? "

C ++ 라이브러리 개발자라면 원시 포인터와 관련된 안전하지 않은 코드를 작성하고 신중하고 책임감있게 코딩해야합니다. 그러나 전문가가 작성한 자체 포함 된 코드 (더 중요한 것은 전문가가 검토)입니다.


따라서 Bjarne이 말한 것과 같습니다. 일반적으로 쓰레기를 수집하려는 동기는 없지만 쓰레기를 생산하지는 않습니다. GC는 C ++의 비영리학이되고 있습니다.

즉, GC가 사용자 정의 할당 및 해당 전략을 사용하려는 경우 특정 응용 프로그램에 대한 흥미로운 문제가 아니라고 말하는 것은 아닙니다. 사람들에게는 언어 수준 GC가 아닌 사용자 정의 할당 및 할당을 원할 것입니다.

원래 C 언어의 기본 원칙 중 하나는 메모리가 일련의 바이트로 구성되며 코드는 사용중인 정확한 순간에 바이트가 의미하는 바에 관심이 있다는 것입니다. 최신 C는 컴파일러가 추가 제한을 부과 할 수 있지만 C는 포인터를 바이트 시퀀스로 분해하고 동일한 값을 포함하는 모든 바이트 시퀀스를 포인터로 조립 한 다음 해당 포인터를 사용하는 기능을 포함합니다. 이전 객체에 액세스하십시오.

이러한 능력은 일부 응용 프로그램에서 유용하거나 필수 불가능할 수 있지만, 그 능력을 포함하는 언어는 유용하고 안정적인 쓰레기 수집을 지원할 수있는 능력이 매우 제한적입니다. 컴파일러가 포인터로 구성된 비트로 수행 된 모든 것을 알지 못하면 포인터를 재구성하기에 충분한 정보가 우주 어딘가에 존재할 수 있는지 알 수있는 방법이 없습니다. 컴퓨터가 그들에 대해 알고 있더라도 컴퓨터에 액세스 할 수없는 방식으로 해당 정보를 저장할 수 있기 때문에 (예 : 포인터를 구성하는 바이트가 누군가가 글을 쓰기에 충분히 오랫동안 표시되었을 수 있습니다. 종이 한 장의 종이), 문자 그대로 컴퓨터가 앞으로 포인터를 사용할 수 있는지 아는 것은 불가능할 수 있습니다.

많은 쓰레기 수집 된 프레임 워크의 흥미로운 기발한 것은 그 안에 포함 된 비트 패턴에 의해 정의되지 않은 객체 참조가 아니라 객체 참조에 고정 된 비트와 다른 곳에서 보유 된 기타 정보 사이의 관계에 의해 정의된다는 것입니다. C 및 C ++에서, 포인터에 저장된 비트 패턴이 물체를 식별하면, 해당 비트 패턴은 물체가 명시 적으로 파괴 될 때까지 해당 물체를 식별합니다. 일반적인 GC 시스템에서, 객체는 한 번에 비트 패턴 0x1234ABCD로 표현 될 수 있지만, 다음 GC 사이클은 모든 참조를 0x1234ABCD로 대체 할 수 있습니다. 객체 참조와 관련된 비트 패턴을 표시 한 다음 나중에 키보드에서 다시 읽어도 동일한 객체 (또는 객체)를 식별하기 위해 동일한 비트 패턴을 사용할 수있을 것으로 기대할 수 없습니다.

모든 기술 대화는 개념을 과도하게 복잡하게하는 것입니다.

모든 메모리에 대해 GC를 C ++에 자동으로 넣으면 자동으로 웹 브라우저와 같은 것을 고려하십시오. 웹 브라우저는 전체 웹 문서를로드하고 웹 스크립트를 실행해야합니다. 문서 트리에 웹 스크립트 변수를 저장할 수 있습니다. 많은 탭이 열린 브라우저의 큰 문서에서 GC가 전체 컬렉션을 수행 할 때마다 모든 문서 요소도 스캔해야 함을 의미합니다.

대부분의 컴퓨터에서 이것은 페이지 결함이 발생 함을 의미합니다. 따라서 질문에 대답하는 주된 이유는 페이지 결함이 발생하기 때문입니다. PC가 많은 디스크 액세스를 시작할 때 이것을 알게 될 것입니다. 유효하지 않은 포인터를 증명하기 위해 GC가 많은 메모리를 터치해야하기 때문입니다. 많은 메모리를 사용하여 선의의 응용 프로그램이 있으면 모든 객체를 스캔 해야하는 경우 페이지 결함으로 인해 모든 컬렉션이 혼란스러워집니다. 페이지 오류는 가상 메모리가 디스크에서 RAM으로 다시 읽어야 할 때입니다.

따라서 올바른 솔루션은 응용 프로그램을 GC가 필요한 부품으로 나누는 것입니다. 위의 웹 브라우저 예제의 경우, 문서 트리가 Malloc과 함께 할당되었지만 JavaScript가 GC와 함께 실행되면 GC가 차기 할 때마다 메모리의 작은 부분 만 스캔하고 메모리의 모든 페인트 요소 만 스캔합니다. 문서 트리가 다시 들어갈 필요가 없습니다.

이 문제를 더 이해하려면 가상 메모리와 컴퓨터에서 어떻게 구현되는지를 찾으십시오. RAM이 실제로 많지 않을 때 프로그램에 2GB를 사용할 수 있다는 사실에 관한 것입니다. 32 비트 시스템 용 2GB RAM이 장착 된 최신 컴퓨터에서는 하나의 프로그램 만 실행중인 경우에는 문제가되지 않습니다.

추가 예로, 모든 객체를 추적 해야하는 전체 컬렉션을 고려하십시오. 먼저 뿌리를 통해 도달 할 수있는 모든 물체를 스캔해야합니다. 두 번째 단계 1에서 볼 수있는 모든 물체를 스캔 한 다음 대기 파괴자를 스캔합니다. 그런 다음 모든 페이지로 이동하여 모든 보이지 않는 개체를 끄십시오. 이것은 많은 페이지가 여러 번 교체 될 수 있음을 의미합니다.

따라서 짧게 가져 오는 내 대답은 모든 메모리를 터치 한 결과 발생하는 페이지 결함의 수가 프로그램의 모든 객체에 대한 전체 GC가 불가능하므로 프로그래머는 GC를 스크립트와 같은 것들에 대한 도움으로보아야한다는 것입니다. 데이터베이스는 작동하지만 수동 메모리 관리로 정상적인 작업을 수행합니다.

물론 다른 매우 중요한 이유는 글로벌 변수입니다. 수집가가 글로벌 변수 포인터가 GC에 있다는 것을 알기 위해서는 특정 키워드가 필요하므로 기존 C ++ 코드는 작동하지 않습니다.

짧은 답변 : 우리는 쓰레기 수집을 효율적으로 (작은 시간과 공간 오버 헤드로) 수행하는 방법을 항상 모르고 (가능한 모든 경우) 항상 정확하게 올바르게 수행합니다.

긴 대답 : C와 마찬가지로 C ++는 시스템 언어입니다. 이것은 시스템 코드 (예 : 운영 체제)를 작성할 때 사용됨을 의미합니다. 다시 말해 C ++는 C와 마찬가지로 가능한 최선의 가능한 성능 주요 목표로. 언어 표준은 성능 목표를 방해 할 수있는 기능을 추가하지 않습니다.

이것은 질문을 일시 중지합니다. 쓰레기 수집이 왜 성능을 방해합니까? 주된 이유는 구현과 관련하여 우리 [컴퓨터 과학자]는 모든 경우에 최소한의 오버 헤드로 쓰레기 수집을 수행하는 방법을 모르기 때문입니다. 따라서 C ++ 컴파일러 및 런타임 시스템은 항상 쓰레기 수집을 효율적으로 수행하는 것은 불가능합니다. 반면에 C ++ 프로그래머는 자신의 설계/구현을 알아야하며 쓰레기 수집을 가장 잘 수행하는 방법을 결정하는 가장 좋은 사람입니다.

마지막으로, 제어 (하드웨어, 세부 사항 등) 및 성능 (시간, 공간, 전력 등)이 주요 제약 조건이 아닌 경우 C ++는 쓰기 도구가 아닙니다. 다른 언어는 더 나은 서비스를 제공하고 필요한 오버 헤드와 함께 더 많은 [숨겨진] 런타임 관리를 제공 할 수 있습니다.

C ++를 Java와 비교할 때 C ++가 암시 적 쓰레기 수집을 염두에두고 설계되지 않았지만 Java는 즉시 알 수 있습니다.

C 스타일 및 결정 론적 소멸자의 임의의 포인터와 같은 것들이 GC 이식의 성능을 늦출뿐만 아니라 많은 양의 C ++-레거시 코드에 대한 후진 호환성을 파괴 할 것입니다.

그 외에도 C ++는 복잡한 런타임 환경을 갖는 대신 독립형 실행 파일로 실행되는 언어입니다.

대체로 : 예, 쓰레기 수집을 C ++에 추가 할 수 있지만 연속성을 위해서는 그렇게하지 않는 것이 좋습니다. 그렇게하는 비용은 혜택보다 클 것입니다.

주로 두 가지 이유로 :

  1. 필요하지 않기 때문에 (IMHO)
  2. C ++의 초석 인 Raii와 거의 양립 할 수 없기 때문입니다.

C ++는 이미 수동 메모리 관리, 스택 할당, RAII, 컨테이너, 자동 포인터, 스마트 포인터를 제공합니다. 쓰레기 수집가는 5 분을 보내고 싶지 않은 게으른 프로그래머를위한 것입니다. 그것은 우리가 C ++에서 일하는 방식이 아닙니다.

쓰레기 수집을 부과하는 것은 실제로 높은 수준에서 높은 수준의 패러다임 전환입니다.

문자열이 쓰레기 수집이있는 언어로 처리되는 방식을 살펴보면 높은 수준의 문자열 조작 기능 만 허용하고 문자열에 이진 액세스를 허용하지 않습니다. 간단히 말해서, 모든 문자열 함수는 먼저 포인터를 점검하여 바이트 만 꺼내더라도 문자열이 어디에 있는지 확인하십시오. 따라서 쓰레기 수집이있는 언어로 문자열로 각 바이트를 처리하는 루프를 수행하는 경우 문자열이 언제 이동했는지 알 수 없으므로 각 반복에 대한 기본 위치와 오프셋을 계산해야합니다. 그런 다음 힙, 스택, 실 등을 생각해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top