문제

멀티 스레드 애플리케이션을 실행할 때 NullReferenceException을 받고 있지만 디버거 이외의 릴리스 모드에서만 실행할 때만 가능합니다. 스택 추적이 기록되고 항상 동일한 기능 호출을 가리 킵니다. 이 기능에 몇 가지 로깅 진술을 넣어 얼마나 멀리 떨어져 있는지 결정하고 기능의 마지막 줄에있는 모든 문장을 포함하여 모든 진술이 기록됩니다. 흥미로운 점은 NullReferenceException이 발생하면 함수 호출 후 명령이 기록되지 않는다는 것입니다.

    // ...
    logger.Log( "one" );  // logged
    Update( false );
    logger.Log( "eleven" );  // not logged when exception occurs
}

private void Update( bool condition )
{
    logger.Log( "one" );  // logged
    // ...  
    logger.Log( "ten" );  // logged, even when exception occurs
}

함수가 호출 될 때마다 예외가 발생하지 않습니다. 리턴 주소가 손실되도록 함수의 실행 전 또는 실행 중에 스택이 손상 될 수 있습니까? 나는 .NET 하에서 그런 종류의 일이 가능하다고 생각하지 않았지만, 낯선 일이 일어난 것 같아요.

기능으로 호출을 함수의 내용으로 교체하려고 시도 했으므로 모든 것이 인라인으로 발생하며 예외는 다음과 같은 선에서 발생합니다.

foreach ( ClassItem item in classItemCollection )

로깅을 통해 "ClassitemCollection"이 Null이 아닌지 확인했으며 Ienumerator가 재미있는 일을하는 경우에 대한 Foreach를 A로 변경하려고 시도했지만 같은 줄에서 예외가 발생했습니다.

이것을 더 조사하는 방법에 대한 아이디어가 있습니까?

업데이트: 몇몇 응답자들은 로거가 무효화되지 않도록 할 수있는 솔루션을 제안했습니다. 명확하게 말하면, 예외가 발생한 후 디버깅 목적으로 로깅 명세서가 추가되었습니다.

도움이 되었습니까?

해결책

나는 내 null 참조를 찾았습니다. Fredrik과 Micahtan이 제안한 것처럼, 나는 지역 사회가 해결책을 찾을 수있는 충분한 정보를 제공하지 않았으므로, 이것을 찾은 내용을 올리기 위해 찾은 것을 게시해야한다고 생각했습니다.

이것은 무슨 일이 일어나고 있는지를 나타내는 것입니다.

ISomething something = null;

//...

// the Add method returns a strong reference to an ISomething
// that it creates.  m_object holds a weak reference, so when
// "this" no longer has a strong reference, the ISomething can
// be garbage collected.
something = m_object.Add( index );

// the Update method looks at the ISomethings held by m_object.
// it obtains strong references to any that have been added,
// and puts them in m_collection;
Update( false );

// m_collection should hold the strong reference created by 
// the Update method.
// the null reference exception occurred here
something = m_collection[ index ];

return something;

문제는 업데이트 방법이 영구적 인 방법을 얻을 때까지 "무언가"변수를 임시 강력한 참조로 사용하는 것으로 판명되었습니다. 릴리스 모드에서 컴파일러는 "something = m_object.add ();"를 최적화합니다. "무언가"가 다시 할당 될 때까지 "무언가"가 사용되지 않기 때문에 과제. 이를 통해 이소질이 쓰레기를 수집 할 수 있었으므로 액세스하려고 할 때 더 이상 m_collection에 존재하지 않았습니다.

내가해야 할 일은 업데이트 호출이 끝날 때까지 강력한 참조를 보장하는 것입니다.

나는 이것이 다른 사람에게 어떤 용도로 사용될 것이라고 의심하지만, 누구나 궁금한 점이 있으면이 질문을 대답하지 않기를 원하지 않았습니다.

다른 팁

"Ten"을 기록한다는 사실은 다음을 먼저 보게 할 것입니다.

  • ~이다 logger 할당 된 적이 ... 이것은 아마도 어떻게 든 무효가 될 것입니다
  • 내부 버그입니다 Log 그 자체

어느 쪽이든 충분한 맥락없이 말하기는 어렵습니다. 그러나 그것이 내가 그것을 조사하는 방법입니다. 간단한 것을 추가 할 수도 있습니다 null 어딘가에 테스트하십시오. 건방진 접근 방식으로 이름을 바꿀 수 있습니다 Log 다른 것에 대한 메소드 및 확장 방법을 추가하십시오.

[Conditional("TRACE")]
public static void Log(this YourLoggerType logger, string message) {
    if(logger==null) {
       throw new ArgumentNullException("logger",
            "logger was null, logging " + message);
    } else {
       try {
           logger.LogCore(message); // the old method
       } catch (Exception ex) {
           throw new InvalidOperationException(
                "logger failed, logging " + message, ex);
       }
    }
}

기존 코드는 새로 호출해야합니다 Log 확장 방법과 예외는 바프가 어디에 있는지 정확히 알 수 있습니다. 일단 고정되면 다시 바꾸거나 떠날 수도 있습니다.

동의 w/fredrik- 자세한 내용은 필요합니다. 모습을 시작할 수있는 한 곳 : 멀티 스레드 애플리케이션과 릴리스에서 발생하는 오류를 언급하지만 디버그는 언급하지 않습니다. 여러 스레드가 동일한 객체 참조에 액세스하여 타이밍 문제가 발생할 수 있습니다.

그럼에도 불구하고, 나는 아마도 다음을 넣을 것입니다.

Debug.Assert(classItemCollection != null);

루프 반복 직전. 릴리스 모드에서는 도움이되지 않지만 디버그에서 발생하는 경우 문제를 포착하는 데 도움이 될 수 있습니다.

로거를 설정하는 코드 또는 부양 가족 중 하나를 NULL로 찾습니다. 널로 설정할 때 이것을 트리거 할 수있는 로거 속성이 있습니까? 릴리스 모드는 때때로 애플리케이션 실행 속도를 높여 디버그 모드 및/또는 디버거의 성능 페널티에 의해 마스크 된 동기화 문제를 나타낼 수 있습니다.

"11 명"이 기록되지 않았다는 사실은 로거가 그 호출이 이루어지기 직전에 NULL로 설정되고 있다고 믿게됩니다. 시도/캐치로 싸서 블록의 캐치 부분에 부딪 치는지 확인할 수 있습니까? 아마도 messagebox.show를 삽입하거나 알려진 파일에 무언가를 쓸 수 있습니다.

여러 스레드에서 ClassitemCollection을 수정하고 있습니까? 다른 스레드에서 컬렉션을 변경하면 반복자를 무효화하여 예외로 이어질 수 있습니다. 잠금 장치로 액세스를 보호해야 할 수도 있습니다.

편집 : Classitem 유형 및 ClassitemCollection 유형에 대한 추가 정보를 게시 할 수 있습니까?

또 다른 가능성은 Classitem이 값 유형이고 ClassitemCollection은 일반적인 컬렉션이며 어떻게 든 Null이 컬렉션에 추가되고 있다는 것입니다. 다음은 nullReferenceException을 던졌습니다.

        ArrayList list=new ArrayList();

        list.Add(1);
        list.Add(2);
        list.Add(null);
        list.Add(4);

        foreach (int i in list)
        {
            System.Diagnostics.Debug.WriteLine(i);
        }

이 특별한 문제는 INT에 의해 해결 될 수 있습니까? I 또는 Object I의 Foreach 또는 Generic Container를 사용합니다.

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