IT

.NET의 MemoryStream이 닫히지 메모리 누수가 발생하고 있습니까?

lottoking 2020. 8. 7. 07:48
반응형

.NET의 MemoryStream이 닫히지 메모리 누수가 발생하고 있습니까?


다음 코드가 있습니다.

MemoryStream foo(){
    MemoryStream ms = new MemoryStream();
    // write stuff to ms
    return ms;
}

void bar(){
    MemoryStream ms2 = foo();
    // do stuff with ms2
    return;
}

내가 할당 한 한 MemoryStream이 폐기되지 않을 가능성이 있습니까?

나는 확실한 수동으로 닫아야한다고 주장하는 피어 리뷰를 검증하는 것이 유효한 포인트가 있는지 여부를 알 수있는 정보를 수 없습니다.


항상이라면 폐기해야합니다. Disposed를 확인하기 위해 메서드에 문을 확인 합니다 .usingbar()ms2

결국 가비지 수집기에 의해 정리 항상 Dispose를 호출하는 것이 좋습니다. 코드에서 FxCop을 실행하면 경고로 표시됩니다.


최소한 현재 구현에서는 아무것도 유출하지 않습니다.

MemoryStream에서 사용하는 메모리가 더 빨리 정리되지 않습니다. 유용하지 않을 또는 당신에게 유용하지 않을 수도 있습니다 호출 후 읽기 / 쓰기 가능한 통화 스트림을 중지합니다.

이 절대적으로 당신 당신이하는 것이 난 웬지 - 결코 스트림의 다른 종류에 MemoryStream을을에서 이동하지 않으려는, 당신에게 폐기를 호출하지 어떤 해 를 할 수 없을거야 . 하지만, 당신은 이제까지 존재하지 않기 때문에 일반적으로 좋은 연습을 할 수 있으며, 당신은 당신이 초기에 쉬운 방법을 선택하기 때문에 찾기 어렵습니다. (반면에 YAGNI 논쟁이 있습니다 ...)

어쨌든이를 수행하는 또 다른 이유는 새로운 구현 Dispose에서 해제되는 리소스를 도입 할 수 것입니다.


거기 예 누출 나중에 얼마나 큰 의미를 정의하고 나중에 얼마나 큰 의미를 따라 ...

누수로 인해 "메모리가 할당 된 상태 남아 있어도 사용할 수 없음"을 의미하고 후자의 경우 폐기를 호출 한 후로 사용할 수 있음을 의미합니다. (예 : 애플리케이션 실행의 수명).

MemoryStream을 사용하는 것이 필요하고 관리되는 메모리를 확보하기 위해, 당신은 그것을 unreference 할가 그래서 바로 가비지 컬렉션 대상이되고, 대한 참조를 무효로합니다. 이 작업을 수행하지 사용을 마친 시점부터 참조가 범위를 때까지 일시적인 누수가 발생합니다. 그 동안에는 메모리를 할당에 사용할 수 없기 때문입니다.

using 문 (단순히 dispose를 호출하는 것보다)의 이점은 using 문에서 참조를 선언 할 수있는 것입니다. 문이 완료 될 때 폐기해야 할 필요가없는 것 참조가 범위를 벗어나야 할 필요없이 즉시 개체를 작성하는 것을 기억할 필요가없는 즉시 개체를 가비지 수집 대상으로 만듭니다.

"메모리 누수는 즉시 해제하지 않는 것이 고전적인"영구적 인 "메모리 누수는 즉시 해제됩니다. 예를 들어, Dispose를 호출 한 후에도 MemoryStream에 대한 참조를 유지하고 메서드에서 조금 더 아래로 더 많은 메모리를 할당하려고하면 ... 여전히 참조 된 메모리 스트림에서 사용중인 메모리를 사용할 수 없습니다. 참조를 무효화하거나 dispose를 호출하여 사용을 완료하고 범위를 때까지


이 이미 답변되어있는 것입니다 은닉의 좋은 구식 원칙은 수 있음을 의미하는 미래 일 것입니다.

MemoryStream foo()
{    
    MemoryStream ms = new MemoryStream();    
    // write stuff to ms    
    return ms;
}

에 :

Stream foo()
{    
   ...
}

스트림이 호출 될 때 어떤 종류의 스트림을 강조하고 내부 구현을 모의 할 수있게합니다 (예 : 단위 테스트를 위해).

바 구현에서 폐기를 사용하지 않는 경우 문제가 발생해야합니다.

void bar()
{    
    using (Stream s = foo())
    {
        // do stuff with s
        return;
    }
}

전화 .Dispose()(또는 래핑 Using)는 필요하지 않습니다.

전화 한 이유 .Dispose()가능한 한 빨리 리소스해제하기 위해서 입니다.

예를 들어 많은 메모리 세트와 수천 개의 요청이 스택 오버플로 서버를 생각해보세요. 예약 된 가비지 수집을 기다리지 않고 최대한 빨리 메모리를 해제하여 사용할 수 있습니다. 새로운 수신 요청.


모든 스트림은 IDisposable을 구현합니다. 메모리 스트림을 문으로 사용면 멋지고 멋질 것입니다. 블록은 스트림이 무엇이든 상관없이 닫히고 삭제합니다.

Foo를 호출 할 때마다 (MemoryStream ms = foo ()) 사용할 수 있으며 여전히 괜찮을 생각합니다.


메모리 누수는 발생하지 않지만 코드 리뷰어는 스트림을 닫아야 함을 표시하는 것이 정확합니다. 그렇게하는 것이 예의입니다.

메모리 누수가 발생할 수있는 유일한 상황은 실수로 스트림에 대한 참조를 남겨두고 닫지 않는 경우입니다. 당신은 여전히 정말 메모리가 누수되지 않습니다,하지만 당신은 하는 당신이 그것을 사용하고 주장하는 것을 불필요하게 시간을 연장.


나는에 MemoryStream을 포장 추천 bar()A의 using중심으로 일관성을 위해 문 :

  • 현재 MemoryStream은에서 메모리를 해제하지 않지만 .Dispose(), 미래의 어느 시점에서 또는 사용자 (또는 회사의 다른 사람)가이를 수행하는 사용자 지정 MemoryStream으로 대체 할 수 있습니다.
  • 프로젝트에서 모든 스트림이 폐기 되도록하는 패턴을 설정하는 데 도움이됩니다. "일부 스트림은 폐기해야하지만 특정 스트림은 폐기 할 필요가 없습니다"대신 "모든 스트림을 폐기해야합니다"라고 말하여 선을 더 확실하게 그립니다. ...
  • 다른 유형의 Streams를 반환 할 수 있도록 코드를 변경 한 경우 어쨌든 삭제하도록 변경해야합니다.

foo()IDisposable을 생성하고 반환 할 때와 같은 경우 에 일반적으로 수행하는 또 다른 작업 은 객체 생성과 return예외 사이의 실패를 확인 하고 객체를 처리하고 예외를 다시 발생시키는 것입니다.

MemoryStream x = new MemoryStream();
try
{
    // ... other code goes here ...
    return x;
}
catch
{
    // "other code" failed, dispose the stream before throwing out the Exception
    x.Dispose();
    throw;
}

개체가 IDisposable을 구현하는 경우 완료되면 .Dispose 메서드를 호출해야합니다.

일부 개체에서 Dispose는 닫기와 동일하며 그 반대의 경우도 마찬가지입니다.

이제 특정 질문에 대해 아니오, 메모리 누수가 발생하지 않습니다.


나는 .net 전문가는 아니지만 아마도 여기서 문제는 리소스, 즉 메모리가 아닌 파일 핸들입니다. 나는 가비지 수집기가 결국 스트림을 해제하고 핸들을 닫을 것이라고 생각하지만, 내용을 디스크로 플러시하도록 명시 적으로 닫는 것이 항상 가장 좋은 방법이라고 생각합니다.


관리되지 않는 리소스의 폐기는 가비지 수집 언어에서 결정적이지 않습니다. Dispose를 명시 적으로 호출하더라도 백업 메모리가 실제로 해제되는시기를 전혀 제어 할 수 없습니다. Dispose는 using 문을 종료하거나 하위 메서드에서 호출 스택을 표시하여 개체가 범위를 벗어날 때 암시 적으로 호출됩니다. 이 모든 것이 말하면 때때로 객체는 실제로 관리 자원 (예 : 파일)의 래퍼 일 수 있습니다. 그렇기 때문에 finally 문에서 명시 적으로 닫거나 using 문을 사용하는 것이 좋습니다. 건배


MemorySteram은 관리 개체 인 바이트 배열에 불과합니다. 폐기하거나 닫는 것을 잊으십시오. 이것은 최종 결정을 내리는 것 외에는 부작용이 없습니다.
리플렉터에서 MemoryStream의 constuctor 또는 flush 메소드를 확인하면 좋은 관행을 따르는 것 외에 닫거나 폐기하는 것에 대해 걱정할 필요가없는 이유가 분명해질 것입니다.

참고 URL : https://stackoverflow.com/questions/234059/is-a-memory-leak-created-if-a-memorystream-in-net-is-not-closed

반응형