개체 참조가 개체의 인스턴스로 설정되지 않았습니다. .NET에서 어떤 개체가 'null'인지 표시하지 않는 이유는 무엇입니까?


103

이 .NET 처리되지 않은 예외 메시지와 관련하여 :

개체 참조가 개체의 인스턴스로 설정되지 않았습니다.

.NET에서 어떤 객체가 표시되지 않는 이유는 무엇 null입니까?

null오류를 확인 하고 해결할 수 있다는 것을 알고 있습니다 . 그러나 .NET이 어떤 개체에 null 참조가 있고 어떤식이 NullReferenceException?

c#  .net 

2
이 경우 발생한 줄을 다시 작성하여 가능한 각 결과가 null인지 먼저 확인합니다. 그러면 정확히 무엇인지 알 수 있습니다. 또는 Visual Studio의 놀라운 디버거가 연결되어 예외가 발생하는 순간을 중단하고 null이 무엇인지 확인할 수 있습니다. :)
Patashu

5
실제로는 .NET 프레임 워크가 프로그래머가 어떤 개체가 null 인지 표시 하는 데 도움이되지 않는 이유를 묻습니다 . 나는 그것이 성능 페널티라고 생각합니다 (반영이 필요합니다). 그러나 나도 확실하지 않습니다.
bas

1
@bas : 사실이지만 질문은 "객체"가 아닌 "표현의 일부"에 대해 질문해야한다는 점에서 약간 오해의 소지가 있습니다. 또한 단순한 리플렉션이 도움이되지 않는 이유를 설명하지만 몇 가지 광범위한 디버그 정보가 필요합니다.
OR Mapper

4
그래도 답이 궁금합니다. 그것은 .NET 예외와 유사한 지적에 도움이되지 떨어져 종류의 어떤 사전에 존재하지 않는 키를 누릅니다. 또한 질문에 대한 열성 인을 이해하지 못합니다.
bas

12
용어 설명 : 개체는 null이 아닙니다. 객체 참조는 하지만 수 있습니다. 그러나 객체 참조는 메모리의 한 위치 일뿐입니다. 어쨌든 디버거가 연결되어 있지 않으면 어떻게 도움이 될까요?
Oskar Berggren 2013

답변:


169

(Visual Studio 2017의 새로운 예외 도우미에 대한 자세한 내용은이 답변의 끝 부분을 참조하세요.)


이 코드를 고려하십시오.

String s = null;
Console.WriteLine(s.Length);

이것은 NullReferenceException두 번째 줄에 a 를 던지고 s예외가 throw되었을 때 .NET 이 null 이라고 말하지 않는 이유를 알고 싶습니다 .

정보를 얻지 못하는 이유를 이해하려면 실행하는 것이 C # 소스가 아니라 IL이라는 점을 기억해야합니다.

IL_0001 : ldnull      
IL_0002 : stloc.0 // 초
IL_0003 : ldloc.0 // 초
IL_0004 : callvirt System.String.get_Length
IL_0009 : System.Console.WriteLine 호출

callvirt를 throw하는 것은 opcode이며 NullReferenceException평가 스택의 첫 번째 인수가 null 참조 (를 사용하여로드 된 참조) 일 때이를 수행합니다 ldloc.0.

.NET이 그것이 snull 참조라는 것을 알 수 있어야한다면 어떤 식 으로든 평가 스택의 첫 번째 인수가 form에서 시작되었음을 추적해야합니다 s. 이 경우 그것이 snull이라는 것을 쉽게 알 수 있지만 값이 다른 함수 호출의 반환 값이고 어떤 변수에도 저장되지 않은 경우 어떻게 될까요? 어쨌든 이러한 종류의 정보는 .NET 가상 머신과 같은 가상 머신에서 추적하려는 정보가 아닙니다.


이 문제를 방지하려면 모든 공용 메서드 호출에서 인수 null 검사를 수행하는 것이 좋습니다 (물론 null 참조를 허용하지 않는 한).

public void Foo(String s) {
  if (s == null)
    throw new ArgumentNullException("s");
  Console.WriteLine(s.Length);
}

메소드에 null이 전달되면 문제가 무엇인지 정확하게 설명하는 예외가 발생합니다 (즉, snull).


4 년 후 Visual Studio 2017에는 a NullReferenceException가 throw 될 때 null이 무엇인지 알려주는 새로운 예외 도우미가 있습니다. null 인 메서드의 반환 값일 때 필요한 정보를 제공 할 수도 있습니다.

Visual Studio 2017 예외 도우미

이것은 DEBUG 빌드에서만 작동합니다.


5
줄 번호와 소스 파일 이름은 IL 코드 자체에 저장되지 않습니다. 그러나 디버깅에 사용할 수 있습니다.
OR Mapper

4
@MartinLiversage : 맞습니다. 따라서 질문은 다음과 같이 요약됩니다 null. 코드의 어떤식이 평가되었는지도 알려주는 기호 파일에 저장된 정보가 충분하지 않은 이유는 무엇입니까?
OR Mapper

2
@MartinLiversage : 예외 발생시 예외 메시지와 함께 소스 파일 및 줄 번호가 디버거의 출력에 표시 될 수 있도록 심볼 파일에 액세스 할 수 있습니다. 따라서 문제는 정확히 반환 된 내용에 대한 추가 정보를 포함하지 않은 이유가 무엇인지 null입니다. OP는 릴리스 빌드의 경우 디버그 빌드로도 충분할 수 있음을 알고 싶어하지 않는다는 점에 유의하십시오.
OR Mapper

3
흠, 우리는 실제로 실행하는 것은 IL조차 아니라 런타임에 빌드 된 네이티브 코드라는 것을 잊지 말아야합니다.
Oskar Berggren 2013

2
@MartinLiversage :이 질문의 아무도 우리가 릴리스 빌드에 대해 완벽하게 지원되기를 원한다고 주장하지 않습니다. 어쨌든, 나는 객체 참조를 사용하는 IL opcode를 null그 객체 참조를 반환 한 소스 파일 라인 및 열과 연관시키는 문제를 잘 알지 못합니다 .
OR Mapper

9

다음과 같은 경우 오류 메시지를 어떻게 표시 하시겠습니까?

AnyObject.GetANullObject().ToString();

private object GetANullObject()
{
  return null;
}

여기에보고 할 변수 이름이 없습니다!


2
OP가 개체가 아닌 null을 반환하는 소스 코드에서 표현식을 찾고 있다고 생각합니다. 나는 질문에 각각의 의견을 추가했으며 그가 일을 해결하기를 바랍니다. 내 의심이 맞다면 OP는 Object reference obtained from AnyObject.GetANullObject() not set to an instance of an object.오류 메시지 와 같은 것을 기대할 것 입니다.
OR Mapper

1
@ORMapper 동의합니다. 댓글을 달 수있는 평판 포인트가 충분하다면 OP에 대한 댓글에 내 "답변"을 넣었을 것입니다!
romar

1
"XYZ 클래스의 ToString () 메서드를 호출하려는 null 참조"가 지금 얻는 것보다 더 유용 할 것입니다.
Michael Levy

가장 유용한 것은 각 호출 수준에서 정확히 어떤 줄, 어떤 파일에서 오류가 발생했는지 보여주는 스택 추적입니다. 아, 잠깐만 요 ... 그게 지금하는 일입니다!
Jim Balter 2015

1

음, Microsoft의 엔지니어가 대답해야합니다. 그러나 분명히 디버거를 사용하고 시계를 추가하여 어느 것이 문제가 있는지 알아낼 수 있습니다.

그러나 예외는 NullReferenceException참조 가 존재하지 않음 을 의미 합니다 . 전혀 생성되지 않은 개체는 가져올 수 없습니다.

but why .NET don't tell us which object is null? 어떤 객체가 null인지 모르기 때문입니다. 개체는 단순히 존재하지 않습니다!

C #이 .NET IL 코드로 컴파일되었다고 말할 때도 마찬가지입니다. .NET IL 코드는 이름이나 식을 알지 못합니다. 참조와 위치 만 알고 있습니다. 여기에서도 존재하지 않는 것을 얻을 수 없습니다. 표현식 또는 변수 이름이 없습니다.

철학 : 애초에 달걀이 없으면 오믈렛을 만들 수 없습니다.


3
bas

참조가 존재하지 않는 경우 어떻게 얻습니까? @Bas
아니 켓 인게

4
"음, Microsoft의 엔지니어가 대답해야합니다." 그러니 그들이 명백한 말 대신에 이것에 대해 밝히도록하자
bas

@bas 우리는 적어도 논리적 인 것을 결정할 수 있습니다. 논리적으로 개체가 존재하지 않습니다. 예외를 가지고 그것을 잡은 다음 객체의 이름을 어떻게 인쇄합니까? 존재하지 않습니다. 스택에도 ..
Aniket Inge 2013

그래서 대답은 그것이 어떤 객체가 nullreference를 가지고 있는지 지적하는 것이 사실상 불가능하다는 것입니다. 그것도 대답입니다. 나는 내가 알고 있다고 말하는 것이 아니라 질문을 좋아합니다 :). 모든 +1 노력 : P
BAS

1

확실하지는 않지만 .Net이 미리 정의 된 클래스인지 사용자 정의인지 알지 못하기 때문일 수 있습니다. 미리 정의 된 경우 null (예 : 2 바이트를 차지하는 문자열)이 될 수 있지만 사용자가 정의한 경우 인스턴스를 만들어야이 개체가이 정도의 메모리를 차지한다는 것을 알 수 있습니다. 따라서 런타임에 오류가 발생합니다.


-2

좋은 질문. 메시지 상자는 쓸모가 없습니다. 참조 정의에서 1 마일 깊이 묻혀 있어도 일부 클래스 나 어셈블리 또는 파일 또는 기타 정보가 현재 제공하는 것보다 낫습니다 (읽기 :없는 것보다 낫습니다).

가장 좋은 방법은 디버깅 정보와 함께 디버거에서 실행하는 것입니다. 그러면 IDE가 문제가되는 줄에서 중단됩니다 (실제로 유용한 정보를 사용할 수 있음을 명확하게 보여줌).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.