Pergunta

Eu tenho o seguinte código:

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

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

Existe alguma chance de que o MemoryStream que eu alocados de alguma forma não conseguem ser eliminados mais tarde?

Eu tenho uma revisão por pares insistindo que eu manualmente perto disso, e eu não posso encontrar as informações para dizer se ele tem um ponto válido ou não.

Foi útil?

Solução

Se algo é descartável, você deve sempre Dispor. Você deve estar usando um usando declaração em seu método bar () para se certificar de MS2 recebe Disposed.

Ele acabará por se limpar pelo coletor de lixo, mas é sempre uma boa prática Descarte. Se você executar FxCop em seu código, ele iria marcá-lo como um aviso.

Outras dicas

Você não vai vazar qualquer coisa -. Pelo menos no atual implementação

Chamando Descarte não irá limpar a memória usada pelo MemoryStream mais rápido. É irá parar seu fluxo de ser viável para chamadas de leitura / gravação após a chamada, o que pode ou não ser útil.

Se você é absolutamente certo que você não quiser mudar de um MemoryStream para outro tipo de fluxo, isso não vai fazer nenhum mal ao não chamar Dispose. No entanto, é geralmente uma boa prática em parte porque se você nunca do mudança de usar um fluxo diferente, você não quer ser mordido por um bug-to hard-encontrar, porque você escolheu o caminho mais fácil cedo em. (Por outro lado, há o argumento YAGNI ...)

A outra razão para fazê-lo de qualquer maneira é que uma nova implementação pode introduzir recursos que seriam libertados em Dispose.

Sim há a vazamento , dependendo de como você define VAZAMENTO e quanto mais tarde você quer dizer ...

Se por vazamento você quer dizer "os restos de memória alocada, indisponível para uso, mesmo que você é feito usando-o" e por último você quer dizer a qualquer hora depois de chamar Dispose, então aí sim pode haver um vazamento, embora não permanente (ou seja, para a vida de seus aplicativos de tempo de execução).

Para liberar a memória gerenciada utilizada pelo MemoryStream, você precisa unreference it , anulando a sua referência a ele, por isso torna-se elegível para coleta de lixo imediatamente. Se você não fizer isso, então você cria um vazamento temporário a partir do momento que você terminar de usá-lo, até que sua referência sai do escopo, porque, entretanto, a memória não estará disponível para alocação.

O benefício da instrução using (mais simplesmente chamando descarte) é que você pode declarar sua referência na instrução using. Quando os que utilizam acabamentos afirmação, não só é dispor chamados, mas sua referência sai do escopo, efetivamente anulando a referência e fazer o seu objeto se qualifique para coleta de lixo imediatamente sem exigir que você lembre-se de escrever a "referência = null" código.

Enquanto não ter unreference algo imediatamente não é um vazamento clássico memória "permanente", ele definitivamente tem o mesmo efeito. Por exemplo, se você manter a sua referência para o MemoryStream (mesmo depois de chamar dispor), e um pouco mais abaixo no seu método de tentar alocar mais memória ... a memória em uso por seu fluxo de memória ainda referenciada não estará disponível até que você anular a referência ou ele sai do escopo, mesmo que você chamou descarte e são feitas usando-o.

Esta já foi respondida, mas eu só vou acrescentar que o bom princípio antiquado de meios ocultação de informação que você pode, em algum futuro ponto de querer refatorar:

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

para:

Stream foo()
{    
   ...
}

Isso enfatiza que os chamadores não deve importa que tipo de fluxo está sendo devolvido, e torna possível mudar a implementação interna (por exemplo, quando zombando para testes de unidade).

então você vai precisar estar em apuros, se você não tiver usado Descarte em sua implementação bar:

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

Todos os fluxos implementar IDisposable. Envolva seu fluxo de memória em uma instrução using e você vai ficar bem e dândi. O bloco usando irá garantir o seu fluxo está fechado e descartado, não importa o quê.

onde quer que você chamar Foo você pode fazer usando (ms MemoryStream = foo ()) e eu acho que você ainda deve estar ok.

Chamando .Dispose() (ou embrulho com Using) não é necessária.

A razão que você chamar .Dispose() é liberar o recurso o mais rápido possível .

Pense em termos de, por exemplo, o servidor Stack Overflow, onde temos um conjunto limitado de memória e milhares de pedidos que nos chegam. Nós não querem esperar em torno de coleta de lixo programada, queremos liberar essa memória o mais rápido possível por isso é disponível para novos pedidos recebidos.

Você não vai vazar memória, mas seu revisor código está correto para indicar que deve fechar seu fluxo. Ele é educado para fazer isso.

A única situação em que você pode vazar memória é quando você acidentalmente deixar uma referência para o fluxo e nunca fechá-lo. Você ainda não está realmente com vazamento de memória, mas você são estendendo desnecessariamente a quantidade de tempo que você alega ser a usá-lo.

Eu recomendaria envolvendo o MemoryStream na bar() em um comunicado using principalmente para a consistência:

  • Agora MemoryStream não memória livre no .Dispose(), mas é possível que em algum momento no futuro, poder, ou você (ou alguém em sua empresa) pode substituí-lo com seu próprio MemoryStream personalizado que faz, etc.
  • Ela ajuda a estabelecer um padrão no seu projeto para garantir todas Streams obter dispostos - a linha é mais firmemente puxado por dizer "todos os fluxos devem ser eliminados" em vez de "alguns Streams devem ser eliminados , mas certas pessoas não têm que" ...
  • Se você mudar o código para permitir o retorno de outros tipos de córregos, você precisará alterá-lo para dispor de qualquer maneira.

Outra coisa que eu costumo fazer em casos como foo() ao criar e retornar um IDisposable é garantir que qualquer falha entre construir o objeto eo return é pego por uma excepção, dispõe o objeto, e relança a exceção:

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;
}

Se um objeto implementa IDisposable, você deve chamar o método .Dispose quando você está feito.

Em alguns objetos, Descarte significa o mesmo que Feche e vice-versa, nesse caso, qualquer um é bom.

Agora, para sua pergunta específica, não, você não vai vazar memória.

Não sou especialista .net, mas talvez o problema aqui é recursos, ou seja, o identificador de arquivo, e não de memória. Eu acho que o coletor de lixo acabará por libertar o fluxo, e perto do punho, mas eu acho que seria sempre a melhor prática para fechá-la explicitamente, para se certificar de que você expulsar o conteúdo no disco.

Descarte de recursos não gerenciados é não-determinístico em linguagens de lixo coletado. Mesmo se você chamar Dispose explicitamente, você absolutamente não tem controle sobre quando a memória de apoio é realmente liberado. Dispose é chamado implicitamente quando um objeto sai do escopo, seja por sair a instrução usando, ou aparecendo a pilha de chamadas a partir de um método subordinado. Este ser tudo dito, por vezes, o objeto pode realmente ser um wrapper para um recurso gerenciado (por exemplo, arquivo). É por isso que é uma boa prática para fechar explicitamente na finalmente declarações ou usar a instrução usando. Felicidades

MemorySteram nada mais é do conjunto de byte, que é gerido objeto. Esqueça de se desfazer ou fechar esta tem nenhum efeito colateral que não seja sobre a cabeça de finalização.
Basta verificar constuctor ou método flush de MemoryStream no refletor e será claro por que você não precisa se preocupar em fechar ou descartar-lo que não seja apenas para questão de seguir as boas práticas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top