2013-07-14 4 views
1

의 정수를 저장하는 다음과 같은 코드를 살펴 있나요? 하나는 그렇지 않다고 가정합니다. 그러나, 디버거를 수행 할 수 있습니다 라인 { } // do something evil here에 중단 점을 넣고 계속하기 전에 직접 실행 창에서 다음 명령을 실행우회 C 번호의 형 보호 및 문자열

((object[])myArray)[0] = 99; 
s = myArray[0]; 

실행이 계속 This should not happen가 인쇄됩니다. Visual Studio 2008에서 테스트되었습니다.

screenshot

디버거에서만 가능 속임수의 종류 또는 코드에서와 같은 "안전하지 않은 과제"를 할 수있는 몇 가지 방법이 있습니다 : 여기에 스크린 샷은 무엇입니까?

는 (물론, 나는 단지 과학적인 호기심. This question에서 요청과 관련된 의견은 나에게이 질문을했다.)

+1

"디버거가 누가 디버그합니까?"질문 중 하나라고 생각합니다. VS 디버거에서 버그를 발견했다고 생각합니다. – dasblinkenlight

+0

매우 흥미로운 주제이지만,이 질문은 귀하가 링크 한 질문과 중복되는 것이 아닙니다. –

+1

규칙을 깨뜨릴 수 있다는 것은 디버거의 핵심입니다. 임의로 코드 실행 순서를 변경하고, 스레드를 고정 시키며, 문자열을 변경하고, GC 힙에서 바이트를 직접 가져올 수 있습니다. 물론 코드에서이 작업을 수행 할 수 있으므로 포인터로 원하는 것을 뽑을 수 있습니다. 단지별로 유용하지 않습니다. –

답변

2

한 기술은 임의의 객체 캐스트를 재 해석하는 데 사용할 수있는 조합을 구현하기 위해 LayoutKind.Explicit을 사용하고 있습니다 문자열에. 먼저 int를 상자에 넣은 다음 합집합의 object 필드에 할당 한 다음 문자열 필드를 읽습니다.

[StructLayout(LayoutKind.Explicit)] 
public struct Evil 
{ 
    [FieldOffset(0)] 
    public string s; 

    [FieldOffset(0)] 
    public object o; 
} 

string ReinterpretCastToString(object o) 
{ 
    Evil evil=new Evil(); 
    evil.o=o; 
    return evil.s; 
} 

void Main() 
{ 
    string s = ReinterpretCastToString(1); 

    if (s.GetType() == typeof(int)) 
    { 
     Console.WriteLine("This should not happen!"); 
    } 
} 

이 언제든지 작동하지 않을 가능성이 정의되지 않은 동작입니다. 분명히 이것을 실제 프로그램에서 사용해서는 안됩니다.

+0

문자열의 크기를 컴파일 타임에 알 수 없기 때문에 컴파일 할 때조차도 놀랍습니다. –

+1

@RobertHarvey 모든 참조는 CPU 아키텍처에 따라 4 또는 8 바이트 크기가 동일합니다. 이것은 기본적으로 한 포인터 유형에서 다른 포인터 유형으로 변환합니다. – CodesInChaos

+0

젠장, 내 프로젝트 중 하나에서 사용되는 세 번째 파트의 lib가 실제로이 기술을 사용하여'int []'와'float []'사이에 캐스트하는 것으로 나타났습니다. – CodesInChaos