2010-01-27 3 views
19

나는 C#에서 참조 형식 만 가비지 수집된다는 사실에 대해서는 약간 혼란 스럽다. 즉, GC는 메모리 할당 해제를위한 참조 유형 만 선택합니다. 그렇다면 값 유형은 스택의 메모리를 차지하므로 어떤 일이 발생합니까?C#에서 구조체 객체를 파기 하시겠습니까?

답변

29

스택에 있거나 힙의 일부가 있는지 여부는 그들이 포함하고있는 컨텍스트에 따라 달라집니다. 참조 유형 내에 있으면 어쨌든 힙에있게됩니다. (당신은 어쨌든 당신이 정말로 스택/힙 분할 얼마나 소중히 생각한다 - 에릭 Lippert의 쓴 것처럼, 그것은 largely an implementation detail입니다.)

그러나, 상황이 재생 될 때 기본적으로 값 형식 메모리가 회수 - 스택은 그래서 때 스택 프레임 전체를 "회수"하는 메서드에서 돌아와서 갑자기 튀어 나옵니다. 마찬가지로 값 형식 값이 실제로 개체의 일부인 경우 해당 개체가 가비지 수집 될 때 메모리가 회수됩니다.

짧은 대답은 당신이 그것에 대해 걱정할 필요가 없다는 것입니다 :) (이것은 당신이 걱정할 메모리보다 다른을 가지고 있지 않다고 가정합니다. 참조가있는 구조체가 있다면 해제 필요가 기본 핸들에, 그것은 다소 다른 시나리오입니다.)

+0

이 포괄적 인 기사를 참조 해 주셔서 감사합니다. 에릭 리 퍼트 (Eric Lippert)의 글로벌 지시문은 전체적인 C# 철학과 매우 일치한다는 것을 알게되었습니다. "의미론에만 관심을두면 나머지 부분을 처리해줍니다" –

3

스택의 값 유형이 범위를 벗어나면 스택에서 제거됩니다.

3

값 유형이 범위를 벗어나 자마자 삭제됩니다.

0

값 형식은 스택 프레임이 실행 된 후에 내가 생각할 겁니다 제거 될 때 할당 해제 할

0

또한 스택에 있습니다 추가 하시겠습니까 스레드 레벨 및 힙은 응용 프로그램 도메인 수준에 있습니다.

따라서 스레드가 종료되면 특정 스레드가 사용하는 스택 메모리를 다시 계산합니다.

7

이 질문에 사용 된 동사가 너무 많습니다 (예 : 파괴됨, 교정 됨, 할당 취소 됨, 제거됨). 그것은 실제로 일어나는 것과 잘 일치하지 않습니다. 지역 변수는 단순히 더 이상 종료되지 않습니다. Norwegian parrot style.

메서드는 단일 진입 점을 가지므로 먼저 발생하는 것은 CPU 스택 포인터가 조정된다는 것입니다. "스택 프레임"생성, 로컬 변수를위한 저장 공간. CLR은이 공간이 0으로 초기화되도록 보장합니다. 그렇지 않으면 명확한 할당 규칙 때문에 C#에서 강력하게 사용하는 기능이 아닙니다.

메서드 코드가 여러 return 문으로 뒤집어 졌을지라도 메서드에는 단일 종료 점이 있습니다. 이 시점에서 스택 포인터는 원래 값으로 간단히 복원됩니다. 실제로 그것은 지역 변수가 그곳에있는 곳을 "잊어 버린다". 그 값은 어떤 식 으로든 '문질러 뜯지'않고, 바이트는 여전히 존재합니다. 그러나 그들은 오래 머 무르지 않을 것입니다. 프로그램의 다음 호출은 다시 덮어 씁니다. CLR 0 초기화 규칙은 안전하지 않은 오래된 값을 결코 관찰 할 수 없도록합니다.

매우 빠르며 단일 프로세서 사이클을 넘지 않습니다. C# 언어에서이 동작의 눈에 보이는 부작용은 값 형식에 finalizer를 사용할 수 없다는 것입니다. 추가 작업을 수행하지 않아도됩니다.

+0

이 로컬 변수는 더 이상 존재하지 않습니다! 그것은 끝났다! 그것은 전 변수입니다. :) –

17

사실 C#에서는 참조 형식 만 가비지 수집된다는 사실에 대해 약간 혼란 스럽습니다.

이것은 사실이 아닙니다.또는 오히려이 진술의 진위 또는 거짓은 "가비지 수집"이 의미하는 바에 달려 있습니다. 가비지 컬렉터는 수집 할 때 값 유형을 확실히 찾습니다. 그 값 유형은 살아 있고 참조 형식에 들고있을 수 있습니다

struct S { public string str; } 
... 
S s = default(S); // local variable of value type 
s.str = M(); 

는 그 s.str이 아직 살아 결정해야하기 때문에 가비지 수집기,의에 보이는 확실히 그것을 실행할 때.

제 제안 : 정확하게 "get garbage collected"라는 동사의 의미를 명확히하십시오.

GC는 메모리 할당 해제에 대한 참조 유형 만 선택합니다.

다시 말하지만 이것은 사실이 아닙니다. 는 가비지 수집 힙 것이다

class C { int x; } 

정수에 대한 메모리의 인스턴스를 가지고, C의 인스턴스 루팅 해제 될 때 그러므로 가비지 수집기 회수하자.

가비지 컬렉터가 참조 유형의 메모리 만 할당을 취소한다고 생각하는 이유는 무엇입니까? 올바른 진술은 가비지 컬렉터에 의해이 할당 된 메모리가 가비지 컬렉터에 의해 으로 할당 해제되었습니다. 가비지 수집기가 완벽하다고 생각합니다. GC가 그것을 할당 했으므로 GC가 정리할 책임이 있습니다.

그래서 스택의 메모리를 차지하므로 값 유형이 어떻게됩니까?

아무런 문제가 발생하지 않습니다. 아무것도 그들에게 일어날 필요가 없습니다. 스택은 백만 바이트입니다. 스택의 크기는 스레드가 시작될 때 결정됩니다. 그것은 백만 바이트에서 시작하고 스레드의 전체 실행을 통해 백만 바이트를 유지합니다. 스택의 메모리가 생성되거나 파괴되지 않습니다. 해당 내용 만 변경됩니다.

+26

"스택상의 메모리가 생성되거나 파괴되지 않습니다"- 우리는 이것을 Lippert의 [Stack] Memory Preservation ** 법칙이라고 부릅니다. :) –

0

.NET의 모든 값 유형 인스턴스는 다른 값 유형 인스턴스, 힙 오브젝트 또는 스택 프레임이 될 수있는 다른 일부의 일부입니다. 그러한 것들이 존재하게 될 때마다 그 안에있는 어떤 구조도 생겨날 것입니다. 그 구조는 그때 그것을 포함하는 것이하는 한 계속 존재할 것이다. 구조를 포함하는 것이 존재하지 않을 때 구조는 또한 존재할 것입니다. 컨테이너를 파괴하지 않고 구조를 파괴 할 수있는 방법이 없으며 거기에 포함 된 구조를 파괴하지 않고 하나 이상의 구조를 포함하는 것을 파괴 할 방법이 없습니다.

관련 문제