범위 기반 메모리 관리의 단점


38

C ++ 커뮤니티에서 더 일반적으로 (혼란스럽게?) 참조하는 범위 기반 메모리 관리 (SBMM) 또는 RAII를 정말 좋아 합니다. 내가 아는 한, C ++ (및 C)을 제외하고는 오늘날 SBMM / RAII를 주요 메모리 관리 메커니즘으로 만드는 다른 주류 언어는 없으며 대신 가비지 수집 (GC)을 선호합니다.

다소 혼란 스럽습니다.

  1. SBMM은 프로그램을보다 결정 론적으로 만듭니다 (객체가 언제 파괴되는지 정확히 알 수 있습니다).
  2. GC를 사용하는 언어에서는 종종 수동 리소스 관리 (예 : Java에서 파일 닫기 참조)를 수행해야합니다. 이는 GC의 목적을 부분적으로 상실하고 오류가 발생하기 쉽습니다.
  3. 힙 메모리는 (매우 우아하게도 imo) 범위에 바운드 될 수 있습니다 ( std::shared_ptrC ++ 참조 ).

SBMM이 더 널리 사용되지 않는 이유는 무엇입니까? 단점은 무엇입니까?


1
몇 가지 단점 (특히 속도와 관련하여)은 Wikipedia에서 논의됩니다 : en.wikipedia.org/wiki/…
Philipp

2
Java의 수동 자원 관리 문제는 finalize()가비지 콜렉션 전에 오브젝트의 메소드가 호출 되는 것을 보장하지 않는 부작용 입니다. 실제로, 이것은 가비지 콜렉션이 해결해야하는 것과 동일한 클래스의 문제점을 작성합니다.
Blrfl

7
@Blrfl 넌센스. "문제"가 존재하지 않더라도 "수동"리소스 관리 (메모리 이외의 리소스의 경우)가 바람직합니다. 리소스가 사용되지 않거나 전혀 실행되지 않은 후에도 GC가 오랫동안 실행될 수 있기 때문입니다. 즉에 대한 아무 문제 없습니다 메모리메모리 관리는 가비지 컬렉션이 해결하도록되어있는 모든 것입니다.

4
btw. 동일한 메커니즘을 사용하여 메모리뿐만 아니라 일반적인 리소스를 관리 할 수 ​​있기 때문에 SBRM이라고합니다.
PlasmaHH

답변:


27

메모리가 다른 모든 리소스보다 훨씬 더 일반적이라고 가정합니다 (수십, 수백 또는 수천 시간). 모든 단일 변수, 객체, 객체 멤버에는 할당 된 메모리가 필요하며 나중에 해제됩니다. 열려있는 모든 파일에 대해 파일에서 가져온 데이터를 저장하기 위해 수십에서 수백만 개의 개체를 만듭니다. 모든 TCP 스트림은 스트림에 쓰도록 작성된 무제한의 임시 바이트 문자열과 함께 사용됩니다. 우리는 같은 페이지에 있습니까? 큰.

RAII가 작동하려면 (햇빛 아래에서 모든 사용 사례에 대해 기성품 스마트 포인터가 있더라도) 소유권 을 가져야합니다 . 이 객체 또는 그 객체를 소유 한 사람, 소유하지 않아야하는 대상 및 A에서 B로 소유권을 이전해야하는시기를 분석해야합니다. 물론 모든 것에 대해 공유 소유권을 사용할 수 있지만 스마트 포인터를 통해 GC를 에뮬레이션합니다. 그 시점에서 훨씬 쉬워집니다 언어로 GC를 구축하는 것이 더 빠릅니다.

가비지 콜렉션은 가장 일반적으로 사용되는 리소스, 메모리에 대한 이러한 문제를 해결합니다. 물론, 다른 자원에 대해서도 동일한 결정을 내려야하지만, 자원은 훨씬 덜 일반적이며 (위 참조), 복잡한 (예 : 공유) 소유권도 덜 일반적입니다. 정신적 부담이 크게 줄어 듭니다.

이제 모든 값을 가비지 수집 하도록 단점을 지정 합니다. 그러나 메모리 안전 GC 값 유형을 RAII와 함께 하나의 언어로 통합하는 것은 매우 어렵 기 때문에 다른 수단을 통해 이러한 절충을 완화하는 것이 더 낫습니까?

결정 론적 손실은 실제로 결정 론적 객체 수명 에만 영향을 미치기 때문에 그다지 나쁘지 않은 것으로 판명되었습니다 . 다음 단락에서 설명하는 것처럼, 대부분의 리소스 (메모리는 많고 다소 느리게 재활용 할 수있는 메모리 제외)는 이러한 언어의 개체 수명에 바인딩 되지 않습니다 . 몇 가지 다른 유스 케이스가 있지만 내 경험으로는 드 rare니다.

두 번째 요점 인 수동 자원 관리는 현재 범위 기반 정리를 수행하지만 오브젝트 정리 시간에이를 정리하지 않는 (GC 및 메모리 안전과 상호 작용하지 않는) 명령문을 통해 해결됩니다. 이것은 최신 Java 버전의 usingC #, withPython의 try-with-resources에 있습니다.


1
이것은 왜 GC와 같은 비결정론 적 모델이 결정 론적 모델보다 우월해야 하는지를 설명하지 못한다. using진술은 로컬에서만 가능합니다. 그런 식으로 멤버 변수에 보유 된 리소스를 정리하는 것은 불가능합니다.
Philipp

8
모두를위한 @Philipp 공유 소유권 이다 GC에, 그냥 아주 가난한. 계산 횟수를 암시하기 위해 "공유 소유권"을 사용하는 경우에는 그렇게 말하지만 amon의 답변에 대한 의견에주기에 대한 토론을 계속하십시오. 또한 참조 계산이 OP에 관심이 있다는 의미에서 결정론 적인지 여부는 확실하지 않습니다 (객체는 가능한 한 빨리 해제되고주기가 할인되지만 프로그램을보고 언제인지 알 수 없습니다). 또한 모든 것에 대한 참조 횟수는 현대 추적 GC보다 훨씬 느립니다.

16
usingRAII에 비해 농담입니다.
DeadMG

3
@Philipp "superior"에 대한 측정 항목을 설명하십시오. 메모리 관리를 위해 수동 메모리 관리가 런타임에 더 빠르다는 것은 사실입니다. 그러나 소프트웨어 비용은 메모리 관리에만 소비되는 CPU 시간만으로는 판단 할 수 없습니다.
ArTs

2
@ ArTs : 나는 이것에 반드시 동의하지는 않습니다. RAII에는 개체가 범위를 벗어나면 파괴되어야한다는 요구 사항이 있습니다. 그런 다음 n 개의 객체를 제거하려면 루프가 필요합니다. 현대 세대의 GC에서 이러한 파괴는 루프가 끝날 때까지 또는 심지어 나중에 연기 될 수 있으며 한 번의 작업으로 수백 번 반복되는 메모리를 파괴 할 수 있습니다. 좋은 경우 GC 매우 빠를 있습니다.
Phoshi

14

RAII는 또한 예를 들어 Perl에 의해 사용되는 자동 참조 카운팅 메모리 관리에 따른다. 참조 카운팅은 구현하기 쉽고 결정 론적이며 성능이 뛰어나지 만 순환 참조를 처리 할 수 ​​없으며 (누수가 발생하여) 일반적으로 사용되지 않습니다.

가비지 수집 언어 RAII를 직접 사용할 없지만 종종 동등한 효과를 가진 구문을 제공합니다. Java에는 try-with-resource 문이 있습니다

try (BufferedReader br = new BufferedReader(new FileReader(path))) { ... }

.close()블록 종료시 리소스 를 자동으로 호출 합니다. C #에는 명령문을 떠날 때 호출 할 IDisposable수 있는 인터페이스 .Dispose()가 있습니다 using (...) { ... }. 파이썬에는 다음과 같은 with진술이 있습니다.

with open(filename) as f:
    ...

비슷한 방식으로 작동합니다. 이것에 대한 흥미로운 스핀에서 Ruby의 파일 열기 메소드는 콜백을 얻습니다. 콜백이 실행 된 후 파일이 닫힙니다.

File.open(name, mode) do |f|
    ...
end

Node.js는 동일한 전략을 사용한다고 생각합니다.


4
자원 관리에 고차 함수를 사용하는 것은 Ruby보다 훨씬 더 오래된 날짜입니다. Lisps에서는 with-open-filehandle파일을 여는 함수가 함수를 생성하고 함수가 리턴되면 파일을 다시 닫는 함수를 갖는 것이 일반적입니다.
Jörg W Mittag

4
순환 참조 인수는 매우 일반적이지만 실제로 얼마나 중요합니까? 소유권이 명확한 경우 약한 포인터를 사용하여 순환 참조를 완화 할 수 있습니다.
Philipp

2
@Philipp 참조 카운트를 사용할 때 일반적으로 소유권 명확 하지 않습니다 . 또한이 답변은 독점적으로 자동으로 참조 계산을 사용하는 언어에 대해 설명하므로 약한 참조는 존재하지 않거나 강한 참조보다 사용하기가 훨씬 어렵습니다.

3
@Philipp 순환 데이터 구조는 복잡한 그래프로 작업하지 않는 한 매우 드 rare니다. 약한 포인터는 일반적인 순환 객체 그래프에서 도움이되지 않지만 트리의 부모 포인터와 같은 일반적인 경우에는 도움이됩니다. 좋은 해결 방법은 전체 그래프에 대한 참조를 나타내는 컨텍스트 개체를 유지하고 소멸을 관리하는 것입니다. 리 카운팅은 거래 중단자가 아니지만 프로그래머가 제한 사항을 잘 알고 있어야합니다. 즉, GC보다인지 비용이 약간 높습니다.
amon

1
참조 카운트가 거의 사용되지 않는 중요한 이유는 단순함에도 불구하고 GC보다 느리기 때문입니다.
Rufflewind

14

내 의견으로는 가비지 수집의 가장 설득력있는 장점은 컴포지션이 가능 하다는 것 입니다. 메모리 관리의 정확성은 가비지 수집 환경의 로컬 속성입니다. 각 부분을 개별적으로보고 메모리 누수 여부를 결정할 수 있습니다. 메모리를 수정 한 부품을 원하는만큼 조합하면 제대로 유지됩니다.

참조 횟수를 사용하면 해당 속성이 손실됩니다. 응용 프로그램에서 메모리 누수 여부는 참조 횟수를 사용하여 전체 응용 프로그램의 전역 속성이됩니다. 부품 간의 모든 새로운 상호 작용은 잘못된 소유권을 사용하고 메모리 관리를 중단 할 가능성이 있습니다.

다른 언어로 된 프로그램 디자인에 매우 눈에 띄는 효과가 있습니다. GC 언어의 프로그램은 상호 작용이 많은 객체의 수프보다 더 많은 경향이 있지만 GC가없는 언어에서는 엄격하게 제어되고 상호 작용이 제한된 구조적 부분을 선호하는 경향이 있습니다.


1
정확성은 객체가 해당 참조의 대상이 아닌 자체적으로 참조를 보유하는 경우에만 작성 가능합니다. 알림과 같은 것들이 혼합되면 (Bob은 Joe에게 Bob에게 무언가를 요청하고 Bob이 그렇게하겠다고 약속했지만 Bob은 그렇지 않다면 Joe에게 신경 쓰지 않기 때문에 Joe에 대한 참조를 보유 함) GC 정확성에는 종종 범위가 지정된 리소스 관리가 필요합니다 [GC 시스템에는 C ++의 자동화가 없기 때문에 많은 경우에 수동으로 구현 됨].
supercat

@supercat : "GC 정확성에는 종종 범위가 지정된 리소스 관리가 필요합니다". 뭐라고? 스코프는 소스 코드에만 존재하며 GC는 런타임에만 존재하므로 스코프의 존재를 완전히 알 수 없습니다.
Jon Harrop

@ JonHarrop : C ++ "scoped pointer"와 같은 의미에서 "scope"라는 용어를 사용하고있었습니다. [객체의 수명은 그것을 보유하는 컨테이너의 수명이어야합니다.] 원래 질문에서 암시 된 사용법이기 때문입니다. 내 요점은 객체를 순전히 GC 시스템에서 구성 할 수없는 것과 같은 목적으로 객체가 잠재적으로 오래 지속되는 참조를 생성한다는 것입니다. 정확성을 위해 특정 참조는 강력해야하고, 일부 참조는 약해야하며, 어떤 참조는 오브젝트 사용 방법에 따라 달라져야합니다. 예를 들어 ...
supercat

... 프레드와 바니는 객체를 제공하여 특정 디렉토리의 어떤 것이라도 수정 될 때마다 알림을받습니다. Fred의 핸들러는 요청에 따라 값을보고 할 수 있지만 다른 용도는없는 카운터를 증분시킬뿐입니다. 특정 파일이 수정되면 Barney의 핸들러가 새 창을 표시합니다. 정확성을 위해 Fred는 약한 이벤트를 구독해야하지만 Barney는 강해야하지만 타이머 객체는 그것을 알 수있는 방법이 없습니다.
supercat

@ supercat : 맞습니다. 나는 그것이 "종종"발생한다고 말하지 않을 것이다. 나는 30 년 동안 한 번만 프로그래밍을 해왔다.
Jon Harrop

7

폐쇄는 거의 모든 현대 언어의 필수 기능입니다. GC로 구현하기가 쉽고 RAII를 사용하기가 매우 어렵습니다 (불가능하지는 않지만). 주요 특징 중 하나는 변수의 수명 동안 추상화 할 수 있기 때문입니다!

C ++은 다른 사람들이 40 년 만에 얻을 수 있었으며 많은 똑똑한 사람들이 제대로하기 위해 많은 노력을 기울였습니다. 대조적으로, 프로그래밍 언어의 설계 및 구현에 대한 지식이없는 사람들에 의해 설계되고 구현 된 많은 스크립팅 언어에는 그것들이 있습니다.


9
C ++의 클로저 가 좋은 예 라고 생각하지 않습니다 . C ++ 11의 람다는 functor 클래스 (C ++ 11 이전 버전)의 구문 설탕 일 뿐이며 메모리도 안전하지 않습니다. 참조로 무언가를 캡처하고 해당 항목이 죽은 후 클로저를 호출하면, 유효한 것보다 더 긴 참조를 유지하는 것과 같이 단순히 UB를 얻습니다. 그들이 40 년 늦게 나타난 것은 FP에 대한 뒤늦은 승인 때문이며, FP를 안전하게 만드는 방법을 알아 내기 때문이 아닙니다. 그리고 그것들을 디자인하는 것은 확실히 큰 과제 였지만, 대부분의 노력이 인생의 시간을 고려한 것으로 의심됩니다.

나는 delnan에 동의합니다 : C ++은 클로저를 올바르게 얻지 못했습니다. 호출 할 때 코어 덤프를 원하지 않으면 매우 조심스럽게 프로그래밍해야합니다.
Giorgio

2
@delnan : 참조로 캡처 람다는 매우 의도적으로 그 [&]구문을 가지고 있습니다. 모든 C ++ 프로그래머는 이미 &부호를 참조와 연관시키고 오래된 참조에 대해 알고 있습니다.
MSalters

2
@MSalters 요점은 무엇입니까? 참조 연결을 직접 그렸습니다. 나는 C ++ 람다는 매우 안전하지 않다고 말하지 않았으며, 참조와 마찬가지로 안전하지 않다고 말했다. 나는 C ++ 람다는 나쁘지 않다고 주장하지 않았다. 나는이 답변의 주장에 반대했다.

5
  1. SBMM은 프로그램을보다 결정 론적으로 만듭니다 (객체가 언제 파괴되는지 정확히 알 수 있습니다).

대부분의 프로그래머에게 OS는 비결정론 적이며, 메모리 할당자는 비결정론 적이며, 그들이 작성한 대부분의 프로그램은 동시 적이므로 본질적으로 비결정론 적입니다. 소멸자가 스코프의 끝에서 약간 앞뒤로가 아니라 정확하게 호출되어야한다는 제약을 추가하는 것은 대다수의 프로그래머에게 실질적인 이점이 아닙니다.

  1. GC를 사용하는 언어에서는 종종 수동 리소스 관리 (예 : Java에서 파일 닫기 참조)를 수행해야합니다. 이는 GC의 목적을 부분적으로 상실하고 오류가 발생하기 쉽습니다.

usingC # 및 useF #을 참조하십시오 .

  1. 힙 메모리는 (매우 우아하게도 imo) 범위에 바운드 될 수 있습니다 (C ++의 std :: shared_ptr 참조).

다시 말해, 범용 솔루션 인 힙을 가져 와서 심각하게 제한하는 특정 경우에만 작동하도록 변경할 수 있습니다. 물론 그것은 사실이지만 쓸모가 없습니다.

SBMM이 더 널리 사용되지 않는 이유는 무엇입니까? 단점은 무엇입니까?

SBMM은 수행 할 수있는 작업을 제한합니다.

  1. SBMM은 일류 어휘 클로저로 상향 기능 문제일으 킵니다. 이것이 클로저가 C #과 같은 언어에서는 사용하기 쉽고 C ++에서는 드물고 까다로운 이유입니다. 프로그래밍에서 기능적 구문을 사용하는 일반적인 경향이 있습니다.

  2. SBMM은 소멸자를 필요로하며 함수가 리턴되기 전에 더 많은 작업을 추가하여 테일 호출을 방해합니다. 테일 호출은 확장 가능한 상태 시스템에 유용하며 .NET과 같은 것들에 의해 제공됩니다.

  3. 일부 데이터 구조 및 알고리즘은 SBMM을 사용하여 구현하기가 매우 어렵다. 기본적으로 사이클이 자연스럽게 발생하는 모든 곳. 가장 주목할만한 그래프 알고리즘. 효과적으로 자신의 GC를 작성하게됩니다.

  4. 제어 흐름과 따라서 객체 수명이 본질적으로 결정적이지 않기 때문에 동시 프로그래밍이 더 어렵습니다. 메시지 전달 시스템의 실용적인 솔루션은 메시지를 깊게 복사하고 지나치게 긴 수명을 사용하는 경향이 있습니다.

  5. SBMM은 소스 코드에서 범위가 끝날 때까지 객체를 유지하여 종종 필요 이상으로 길고 필요 이상으로 더 길어질 수 있습니다. 이로 인해 부유 쓰레기의 양이 증가합니다 (연결할 수없는 물체는 재활용 대기 중). 반대로 가비지 콜렉션 추적은 오브젝트에 대한 마지막 참조가 사라진 직후 오브젝트를 해제하는 경향이 있으며, 이는 훨씬 빠릅니다. 메모리 관리 신화 : 신속성을 참조하십시오 .

SBMM은 너무 제한적이므로 프로그래머는 수명을 중첩 할 수없는 상황에서 탈출 경로가 필요합니다. C ++에서는 shared_ptr이스케이프 경로를 제공하지만 가비지 수집 추적보다 ~ 10 배 느릴 수 있습니다 . 따라서 GC 대신 SBMM을 사용하면 대부분의 사람들이 발을 잘못 밟을 수 있습니다. 그러나 그것이 쓸모 없다는 것은 아닙니다. SBMM은 리소스가 제한적인 시스템 및 임베디드 프로그래밍의 맥락에서 여전히 가치가 있습니다.

FWIW에서는 Forth와 Ada를 확인하고 Nicolas Wirth의 작업을 읽어보십시오.


1
어떤 비트를 말하면 기사를 정교하게하거나 인용 할 수 있습니다.
Jon Harrop

2
모든 사용 사례에서 전적으로 사용되는 것이 아니라 몇 가지 드문 사용 사례에서 10 배 더 느리게 관련성이 있습니까? C ++에는 unique_ptr이 있으며 대부분의 경우 충분합니다. 그 다음으로 RAII 트로프 C ++ (많은 사람들이 고풍스러운 언어로 싫어하는 것을 좋아하는 언어)을 공격하는 대신 언어를 공격하는 RAII 트로프를 공격하려는 경우 RAII 가족의 젊은 형제 인 Rust를 사용해보십시오. Rust는 기본적으로 C ++가 잘못한 모든 것을 올바르게 얻는 반면 C ++도 올바르게 얻은 대부분의 것을 얻습니다. 추가 '사용'은 매우 제한된 사용 사례를 제공하고 구성을 무시합니다.
user1703394

2
"모든 유스 케이스에서 전적으로 존재하는 것과는 달리 몇몇 드문 유스 케이스에서 10 배 느리게 관련성이 있습니까?". 첫째, 그것은 순환 인수입니다. shared_ptrC ++에서는 매우 느립니다. 두 번째로, 그것은 사과와 오렌지 비교입니다 (이미 언급 한 기사에서 이미 보여준 바와 같이) shared_ptr. 생산 GC보다 몇 배 느리기 때문 입니다. 셋째, GC는 전적으로 존재하지 않으며 LMax 및 Rapid Addition의 FIX 엔진과 같은 소프트웨어에서는 사용되지 않습니다.
Jon Harrop

1
@Jon Harrop, 만약 당신이 나를 기쁘게하지 않는 경우. 심층 자원 사용의 전이 효과를 완화하기 위해 30 년 이상 동안 어떤 마법 조리법을 사용해 왔습니까? 30 년이 넘는 세월이 지나지 않은 마법의 요리법이 없다면, 당신이 다른 원인에 물린 것으로 잘못 귀인되어 왔을 것입니다.
user1703394

1
@Jon Harrop, shared_ptr은 느리기 때문에 드물지 않습니다. 괜찮은 디자인의 시스템에서 '공유 소유권'이 드물기 때문에 드물습니다.
user1703394

4

TIOBE와 같은 인기 지수 (물론 논쟁의 여지가 있지만 사용하기에 귀하의 질문에 대해 추측 할 것입니다)를 보면 상위 20 개 중 ~ 50 %가 "스크립트 언어"또는 "SQL 언어" "사용 편의성"과 추상화 수단이 결정 론적 행동보다 훨씬 더 중요합니다. 남은 "컴파일 된"언어 중에서 SBMM을 사용하는 언어의 약 50 %가 있고 그렇지 않은 경우 ~ 50 %가 있습니다. 따라서 스크립팅 언어를 계산에서 제외하면 가정이 잘못되었다고 생각합니다. 컴파일 된 언어 중에서 SBMM이있는 언어는 그렇지 않은 언어만큼 인기가 있습니다.


1
"사용 편의성"은 결정론과 어떻게 다릅니 까? 결정 론적 언어가 비결정론 적 언어보다 사용하기 쉬운 것으로 간주되어서는 안됩니까?
Philipp

2
@Philipp 결정 론적이거나 실제로 중요하지 않은 것만. C ++과 친구는 객체 수명에 중요한 많은 것들을 묶을 수 있지만 객체 수명은 그 자체로 중요하지 않습니다. 도달 할 수없는 객체가 해제 되면 정의에 따라 더 이상 사용하지 않기 때문에 중요하지 않습니다.

Perl 및 Python과 같은 다양한 "스크립트 언어"는 메모리 관리를위한 기본 수단으로 참조 계산을 사용합니다.
Philipp

1
@Philipp 적어도 파이썬 세계에서 이것은 언어의 속성이 아닌 CPython의 구현 세부 사항으로 간주됩니다 (거의 다른 모든 구현은 재 계산을 피합니다). 또한 백업주기 GC를 사용하는 catch-all 선택 해제 기준 카운트는 SBMM 또는 RAII로 적합하지 않다고 주장합니다. 사실, 당신은 하드 RAII에 비해 메모리 관리 (그렇지 않은 대부분 때문에, 사이클의 스타일을 고려하는 RAII 지지자를 찾아 누를 것 어디 프로그램에서 다른 곳 프롬프트 해제를 방지 할 수 있습니다).

3

아직 언급하지 않은 GC 시스템의 주요 장점 중 하나는 GC 시스템 의 참조가 존재하는 한 ID를 유지한다는 것 입니다. 참조 사본이 존재하는 동안 오브젝트에서 IDisposable.Dispose(.NET) 또는 AutoCloseable.Close(Java)를 호출하면 해당 사본은 계속 동일한 오브젝트를 참조합니다. 객체는 더 이상 아무 것도 유용하지 않지만, 객체를 사용하려고하면 객체 자체에 의해 예측 가능한 동작이 제어됩니다. 대조적으로, C ++에서 코드가 delete객체를 호출 하고 나중에이를 사용하려고하면 시스템의 전체 상태가 완전히 정의되지 않습니다.

주목해야 할 또 다른 중요한 사항은 범위 기반 메모리 관리가 명확하게 정의 된 소유권을 가진 객체에 매우 효과적이라는 것입니다. 소유권이 정의되지 않은 객체에서는 훨씬 잘 작동하지 않으며 때로는 완전히 나쁘게 작동합니다. 일반적으로 가변 객체에는 소유자가 있어야하지만 불변 객체에는 필요하지 않지만 주름이 있습니다. 코드가 가변 유형의 인스턴스를 사용하여 불변 데이터를 보유하는 경우가 일반적입니다. 인스턴스를 변경시킬 수있는 코드. 이러한 시나리오에서 가변 클래스의 인스턴스는 여러 개의 불변 개체간에 공유 될 수 있으므로 명확한 소유권이 없습니다.


4
전반부에 언급 된 속성은 메모리 안전입니다. GC는 메모리 안전을 달성하는 매우 쉬운 방법이지만 GC는 필요하지 않습니다. Rust를 잘 살펴보십시오.

@delnan : rust-lang.org를 볼 때 브라우저가 유용하게 탐색 할 수없는 것 같습니다. 자세한 정보는 어디서 찾아야합니까? GC가없는 메모리 안전은 응용 프로그램이해야 할 모든 일에 잘 맞지 않을 수있는 데이터 구조에 대한 특정 제한을 부과하지만 잘못된 것으로 입증되어 기쁩니다.
supercat

1
나는 이것에 대한 하나의 (또는 작은 세트의) 좋은 참조를 모른다. 내 Rust 지식은 메일 링리스트 (다양한 튜토리얼, 언어 디자인 블로그 게시물, github 이슈, ThisWeekInRust 등을 포함하여 메일에 링크 된 모든 내용)를 읽는 데 1 년 또는 2 년 동안 축적되었습니다. 귀하의 인상을 간단히 설명하기 위해, 그렇습니다. 각 안전한 구성은 (필수적으로) 제한을 부과하지만, 사실상 모든 메모리 안전 코드에는 적절한 안전한 구성이 존재하거나 작성 될 수 있습니다. 가장 일반적인 언어는 이미 언어와 stdlib로 존재하며 다른 모든 언어는 사용자 코드로 작성할 수 있습니다.

@delnan : Rust는 카운터를 참조하기 위해 연동 업데이트가 필요합니까, 아니면 소유권이 명확하지 않은 불변 객체 (또는 불변 랩핑 가능한 객체)를 처리하는 다른 수단이 있습니까? Rust에 "개체 소유"및 "비 소유"포인터의 개념이 있습니까? 나는 "Xonor"포인터에 관한 논문을 기억하는데, 여기에는 "소유"하는 단일 참조를 가진 객체와 그렇지 않은 다른 참조에 대한 아이디어가 설명되어 있습니다. "소유"참조가 범위를 벗어나면 모든 비 소유 참조는 죽은 객체에 대한 참조가되며 다음과 같이 식별 될 수 있습니다.
supercat

1
Stack Exchange 의견이 언어를 둘러보기에 적합한 매체라고 생각하지 않습니다. 여전히 관심이 있으시면 소스 (#rust IRC, rust-dev 메일 링리스트 등)로 직접 이동하거나 대화방으로 연락하십시오 (하나를 만들 수 있어야합니다).

-2

우선, RAII를 SBMM과 동일시하는 것을 인식하는 것이 매우 중요합니다. 또는 심지어 SBRM. RAII의 가장 필수적인 (그리고 가장 잘 알려지지 않은 또는 가장 잘 알려지지 않은) 자질 중 하나는 '자원이되는 것'을 구성에 전이되지 않는 속성으로 만든다는 사실입니다.

다음 블로그 게시물에서는 RAII의이 중요한 측면에 대해 설명하고 비 결정적 GC를 사용하는 GCed 언어의 리소스 변경과 대조합니다.

http://minorfs.wordpress.com/2011/04/29/why-garbage-collection-is-anti-productive/

RAII는 대부분 C ++에서 사용되지만 Python (VM 기반이 아닌 버전)에는 Python이 RAII를 GC와 함께 사용할 수있는 소멸자 및 결정적 GC가 있습니다. 그렇다면 두 세계의 최고.


1
-1 그것은 내가 읽은 최악의 기사 중 하나입니다.
Jon Harrop

1
언어 문제는 GC를 지원하는 것이 아니라 RAII를 포기한다는 것입니다. 언어 / 프레임 워크가 둘 다를 지원할 수없는 이유는 없습니다.
supercat

1
@Jon Harrop, 정교하게 설명해 주시겠습니까? 이 기사에서 제기 된 주장 중 처음 3 가지 주장 중 하나라도 포함되지 않습니까? 생산성 주장에 동의하지 않을 수도 있지만 다른 3 가지 주장은 절대적으로 유효합니다. 가장 중요한 것은 자원의 전이성에 관한 첫 번째 것입니다.
user1703394

2
@ user1703394 : 첫째, 전체 기사는 실제로 가비지 콜렉션과 관련이없는 경우 "GCed language"를 기반으로합니다. 두 번째로, 그는 실제로 결함이 객체 지향 프로그래밍에있을 때 가비지 콜렉션을 비난합니다. 마침내 그의 주장은 10 년이 너무 늦었다. 대부분의 프로그래머는 이미 높은 생산성을 제공하기 때문에 가비지 수집 언어로 현대화했습니다.
Jon Harrop

1
그의 구체적인 예 (RAM, 열린 파일 핸들, 잠금, 스레드)는 꽤 말하고 있습니다. 마지막으로 직접 처리 한 코드를 작성해야 할 때를 기억하기가 어려웠습니다. RAM을 통해 GC는 모든 것을 자동화합니다. 파일 핸들을 사용 File.ReadLines file |> Seq.length하면 추상화가 닫히는 위치 와 같은 코드를 작성합니다 . 잠금 및 스레드는 .NET Task및 F #으로 대체되었습니다 MailboxProcessor. 이 전체 "우리는 수동 자원 관리의 양을 폭발시켰다"는 말도 안되는 말이다.
Jon Harrop
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.