2017-04-11 1 views
2

참조 기능으로 C# 7.0을 도입 한 이래로이 기능은 힙에있는 변수에만이 참조를 저장하도록 컴파일러에서 다시 배선해야한다는 것을 이해했기 때문에 스택에있는 변수에 대한 참조를 반환했거나 새 ref 선언으로 변수가 항상 힙에 저장되는지 확인합니까?C# 7.0에서 참조로 반환되는 값이 스택이나 힙에 저장됩니까?

ref int x = ref DoSomething(data); 
// Is the value of x now on the stack or the heap? Or is x stored on the stack as a reference and the value on the heap? 

나의 이해는 this article을 기반으로합니다 : 마지막으로

에서, CLR은 "REF 반환 형식을"허용 않습니다; 당신은 이론적으로 정수형 변수 에 대한 참조를 반환하는 "ref int M() {...}"메서드를 가질 수 있습니다. 이상한 이유로 우리가 을 C#에서 컴파일러와 검증자를 고쳐야 만 이 힙에있는 것으로 알려진 변수에 대한 참조를 반환하는 것이 가능하다는 것을 확인해야한다고 생각한 경우 , 또는 스택 아래에 "lower lower"로 알려지기를 원합니다.

+0

로컬 변수 인 경우 스택에있을 것입니다. –

+1

@EhsanSajjad 로컬 변수 인 경우 'ref'를 반환하는 메서드에서 반환 할 수 없습니다. – Servy

+0

@Servy의 의미를 구체적으로 설명해 주시겠습니까? –

답변

10

노래의 이름은 "Haddocks '눈'. '라고 '오, 노래의 이름이 맞습니까?' 앨리스는 흥미를 느끼려 고 말했다. '아니, 너는 이해가 안돼.'기사는 조금 화가 난다고 말했다. '그것이 바로 이름입니다. 이름은 정말로 "노인"입니다. ' '그럼 그 노래가 뭐라고 부르는지 "라고 말 했어야 했습니까?" 앨리스는 자신을 바로 잡았다. '아니, 그럴 필요 없어. 그건 또 다른 문제 야! 그 노래는 "방법과 수단"이라고 불리는데, 그것이 그것이 부르는 것일뿐입니다! '글쎄, 그 노래가 뭐니?' 이 시간까지 완전히 당황한 앨리스는 말했다. '나는 그걸로 갔다.'기사가 말했다. '노래는 정말로 "문에 앉아있다"이다. 그리고 곡은 내 자신의 발명품이다. "

노래, 노래 이름, 이름이 무엇인지, 그리고 노래가 무엇인지 불리는 것이 분명히 다릅니다.


는 혼동하지 않아야 세 가지가 있습니다

  • 변수에 참조의 위치 - 별칭.
  • 변수의 위치는입니다. 은 별칭이입니다.
  • 참조 된 변수가 참조 유형 인 경우 해당 참조 위치 (있는 경우).

ref int x = ref DoSomething(data); 

은 스택 또는 힙에 지금 x의 값인가?

발현 x 다른 변수별명이다.

변수에 값이 있습니다.

앨리어스 된 변수가 값 유형이라고 가정합니다. 임시 풀 (일명 "스택") 또는 장기 풀 ("힙")에서 별칭이 지정된 변수 및 해당 값이 있습니까? 우리는 모른다. 우리는 신경도 쓰지 않습니다. 우리는 그것이 무엇이든지간에, 우리는이 변수가 현재 살아 있다는 것을 보장합니다. 우리가 추측을 만들 수 그러나

은 : 심판 때문에 우리는 그들이 살아 있는지 알고, 변수는 힙 할당 변수 일반적으로 별칭 돌아왔다.

앨리어스 된 변수가 참조 유형이라고 가정합니다. 참조가 스택 또는 힙에 저장되어 있습니까? 다시, 우리는 똑같은 이유로 모릅니다. 은 해당 참조의 참조 대상이 스택 또는 힙에입니까? 힙에 있거나 null입니다. 우리 입니다.

또는 x가 참조 및 힙의 값으로 스택에 저장되어 있습니까? x으로

당신은 x 별칭이, 또는 당신이 지역 x 자체을 의미합니까 것을 에게 변수를 의미합니까? 로컬 자체는 스택 또는 레지스터에 저장됩니다. 클로저 클래스의 필드에는 절대로 올려지지 않습니다. 앨리어스 된 변수는 어디에도있을 수 있지만 위에서 언급했듯이 힙에있을 가능성이 큽니다.

+0

나는 당신의 대답을 좋아합니다. 하지만 C# 7에서는 별칭을 만들면서 변수가 살아 있는지 어떻게 확인할 수 있습니까? 나는 그 순간에 그것을 시도 할 수는 없지만 동일한 메소드 작업에서 로컬 변수 (스택에 대한 참조)를 반환하지 않습니까? – IllidanS4

+0

@ IllidanS4 : 컴파일러는 각 ref가 어디서 왔는지, 발생한 일을 추적해야합니다. 우리가 알고있는 심판을 현지에 돌려 보내는 것은 합법적이지 않습니다. –

+0

모든 경우에 그렇게 할 수 있습니까? 이미 컴파일 된 다른 어셈블리에서 ref-returning ref-taking 메소드가있는 경우에는 제공된 참조 만 리턴합니다. 이 경우에도 컴파일러가 메서드를 확인합니까? – IllidanS4

7

ref int xint* x의 구문 설탕이며 런타임에 변수가 작동하는 방식입니다. 메서드에 변수를 인수로 전달하고 매개 변수가 ref으로 선언되면 호출자는 변수에 대한 포인터를 전달할 때와 똑같은 동작을합니다. 포인터는 값이 저장된 위치를 신경 쓰지 않으며 실제로 아무 데나 저장할 수 있습니다. 속성을 전달할 수는 없으며 저장소가 없습니다.

C# v7에서해야 할 일은 실수로 dangling pointer bug을 만들 수 없도록하는 것입니다. C 및 C++과 같은 언어로 유명한 것은 컴파일러가 진단을 생성 할 필요가없는 언어에서 정의되지 않은 동작입니다. 이 버그가있는 많은 프로그램은 프로그램에서 겉으로는 사소한 변화 (함수 호출 추가)가 뾰족한 값을 손상시킬 때까지 잘 돌아가는 것처럼 보입니다.

afaik를하기에는 실제로 어렵지는 않지만, 호출 된 메소드의 지역 변수가 문제 발생 자입니다. 메서드가 반환 된 후에는 더 이상 존재하지 않으므로 참조가 유효하지 않게됩니다. C# v7에서 컴파일 오류가 발생하는 특정 시나리오. 그러나 로컬 변수가 호출자 중 하나이고 매개 변수를 통해 참조로 전달 된 경우 변수는 여전히 유효합니다.

관련 문제