unsafe 키워드 없이 이 코드가 작동하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/792735

  •  16-09-2019
  •  | 
  •  

문제

~ 안에 답변 자기 자신에게 논란의 여지가 있는 질문, 으깨다 .NET 개체 인스턴스의 바이트를 직접 읽고 쓰는 데 "unsafe" 키워드가 필요하지 않다는 점을 설명했습니다.다음 유형을 선언할 수 있습니다.

   [StructLayout(LayoutKind.Explicit)]
   struct MemoryAccess
   {

      [FieldOffset(0)]
      public object Object;

      [FieldOffset(0)]
      public TopBytes Bytes;
   }

   class TopBytes
   {
      public byte b0;
      public byte b1;
      public byte b2;
      public byte b3;
      public byte b4;
      public byte b5;
      public byte b6;
      public byte b7;
      public byte b8;
      public byte b9;
      public byte b10;
      public byte b11;
      public byte b12;
      public byte b13;
      public byte b14;
      public byte b15;
   }

그런 다음 "불변" 문자열을 변경하는 등의 작업을 수행할 수 있습니다.다음 코드는 내 컴퓨터에 "bar"를 인쇄합니다.

 string foo = "foo";
 MemoryAccess mem = new MemoryAccess();
 mem.Object = foo;
 mem.Bytes.b8 = (byte)'b';
 mem.Bytes.b10 = (byte)'a';
 mem.Bytes.b12 = (byte)'r';
 Console.WriteLine(foo);

또한 AccessViolationException 동일한 기술로 객체 참조를 손상시킵니다.

질문:나는 (순수하게 관리되는 C# 코드에서) 위험한 이런 일을 하려면 키워드가 필요했습니다.여기서는 왜 필요하지 않습니까? 이는 순수하게 관리되는 "안전한" 코드가 실제로 전혀 안전하지 않다는 것을 의미합니까?

도움이 되었습니까?

해결책

좋아, 그것은 불쾌합니다 ... 노동 조합을 사용하는 위험. 그것은 효과가 있지만 그다지 좋은 생각은 아닙니다. 나는 그것을 반사와 비교할 것이라고 생각합니다 (대부분의 일을 할 수있는 곳). 이것이 제한된 액세스 환경에서 작동하는지 알고 싶습니다. 그렇다면 더 큰 문제를 나타낼 수 있습니다 ...


방금 "Full Trust"플래그없이 테스트했으며 런타임은이를 거부합니다.

Offset 0에 겹치는 객체와 어셈블리를 검증 할 수 있어야하기 때문에 Assembly 'ConsoleApplication4, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0, version = 1.0.0.0에서로드 할 수 없습니다.

그리고이 깃발을 갖기 위해서는 이미 높은 신뢰가 필요합니다. 따라서 이미 더 많은 불쾌한 일을 할 수 있습니다. 문자열은 정상적인 .NET 객체가 아니기 때문에 약간 다른 경우입니다. 그러나 그것들을 돌연변이하는 방법의 다른 예가 있습니다. 그러나 "Union"접근법은 흥미로운 것입니다. 또 다른 해킹 방법 (충분한 신뢰 포함) :

string orig = "abc   ", copy = orig;
typeof(string).GetMethod("AppendInPlace",
    BindingFlags.NonPublic | BindingFlags.Instance,
    null, new Type[] { typeof(string), typeof(int) }, null)
    .Invoke(orig, new object[] { "def", 3 });
Console.WriteLine(copy); // note we didn't touch "copy", so we have
                         // mutated the same reference

다른 팁

멍청이, 난 머물러 있었다 unsafe ~와 함께 fixed. 수정 된 버전은 다음과 같습니다.

샘플 코드가 unsafe 키워드는 포함되지 않는다는 것입니다 포인터 (이것이 안전하지 않은 것으로 간주되는 이유는 아래 인용문을 참조하십시오). 당신은 매우 맞습니다. "안전한"은 "런 타임 친화적"이라고 불릴 수 있습니다. 이 주제에 대한 자세한 내용은 Don Box와 Chris Sells를 참조하십시오. 필수 .NET

MSDN,

CLR (Common Language Runtime)에서 안전하지 않은 코드를 검증 할 수없는 코드라고합니다. C#의 안전하지 않은 코드는 반드시 위험하지는 않습니다. CLR에 의해 안전을 확인할 수없는 코드 일뿐입니다. 따라서 CLR은 완전히 신뢰할 수있는 어셈블리에있는 경우 안전하지 않은 코드 만 실행합니다. 안전하지 않은 코드를 사용하는 경우 코드에 보안 위험이나 포인터 오류가 발생하지 않도록해야합니다.

고정과 안전하지 않은 차이점은 고정이 CLR이 메모리에서 물건을 움직이지 못하게하므로 런타임 외부의 물건이 안전하게 액세스 할 수있는 반면 안전하지 않은 것은 반대의 문제에 관한 것입니다. CLR은 정확히 반대 문제에 관한 것입니다. 도트 넷 참조는 포인터에 대해서는 그렇게 할 수 없습니다. 당신은 참조가 어떻게 포인터가 아닌지에 대해 진행되는 다양한 마이크로 소프트를 기억할 수 있으며, 이것이 미묘한 차이에 대해 소란스러운 이유입니다.

여전히 '관리' 비트를 선택 해제하고 있습니다.그렇게 할 수 있다면 자신이 무엇을 하고 있는지 알고 있다는 근본적인 가정이 있습니다.

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