Fugas de memória

Estou a tentar compreender melhor o conceito de fugas de memória. Alguém pode apontar alguma informação útil que pode me ajudar a entender melhor exatamente o que vazamentos de memória são e como eu iria encontrá-los no meu código.

Author: Ivan, 2011-02-16

6 answers

Existem muitos tipos de vazamentos de memória, mas em geral o termo refere-se a algum tipo de recurso que não é mais usado, mas ainda ocupa a memória. Se você tem muitos desses seu aplicativo leva uma grande quantidade de memória e, eventualmente, você fica sem ele.

Em C#, estas são algumas fugas de memória comuns:

  • não remover os ouvintes de eventos. Qualquer ouvinte de eventos que seja criado com um método anônimo ou expressão lambda que referencie um objeto externo irá manter esses objetos vivo. Lembre-se de remover os ouvintes de eventos quando eles já não são usados.
  • manter as ligações de bases de dados ou os conjuntos de resultados abertos quando não são utilizados. Lembre-se de ligar para todos os objectos {[[1]}. utilize a Declaraçãousing.
  • ligue para as funções C usando o p/invoque que atribui a memória que nunca irá libertar.
 37
Author: Markus Johnsson, 2011-02-16 19:36:34
Uma fuga de memória tradicional acontece quando se aloca a memória e, de alguma forma, "esquece" para a libertar. No código C++ antigo, isso significa chamar new sem um delete correspondente. Em C, significou uma chamada para alloc()/malloc() sem um free() correspondente. In. net, you don't get memory leaks in the traditional sense, because you are not supposed to release memory yourself. Em vez disso, você confia no coletor de lixo para liberá-lo para você. No entanto, isto não significa que nunca perderás a memória. Há várias maneiras que você pode acidentalmente manter uma referência ao redor que impede o coletor de lixo de fazer o seu trabalho. Estes incluem variáveis globais (especialmente listas, dicionários, e outros tipos de coleção que podem ser usados para "cache" objetos), manipuladores de eventos que se agarram à memória, referências recursivas de história, e o grande heap objeto.

É importante também notar aqui que só porque você vê um padrão de aumento do uso de memória em .Net, não significa necessariamente que a sua aplicação esteja a perder memória. Em casos de baixa pressão de memória geral, o coletor de lixo poderia simplesmente estar optando por economizar tempo, não coletando ainda, ou coletando dentro do espaço de endereçamento existente do processo apenas sem retornar a memória para o sistema operacional.

 27
Author: Joel Coehoorn, 2018-06-27 20:33:23

Uma boa leitura é Toda a gente pensa na recolha do lixo da forma errada.

Em geral, uma fuga de memória, ou qualquer fuga de recursos, é sempre que o programa aloca a memória (ou qualquer outro recurso) e, em seguida, omite para desacoplar quando terminar com ela. No vazamento de memória de aplicação nativa é o vazamento de recurso mais comum e pode acontecer quando a referência de recurso (o ponteiro para o bloco alocado) sai do escopo e é destruído, mas alocado recurso (a memória block) não é destruído. Neste caso, o recurso (memória) é vazado porque o programa perdeu a capacidade de liberá-lo, mesmo se ele quiser, porque ele já não se lembra da localização do recurso (o endereço do bloco).

Em aplicações controladas, as fugas de memória são um pouco mais complicadas. Uma vez que o tempo de execução pode rastrear referências a recursos automaticamente, ele também pode entender quando um recurso (um objeto) não é mais referenciado por qualquer parte ativa da aplicação (há nenhuma cadeia de referências de uma estrutura de pilha para esse recurso em qualquer thread) e assim o tempo de execução pode entender quando é seguro coletar os objetos não mais referências pela aplicação. Então, no mundo gerenciado, uma 'fuga' ocorreria quando você acredita que o aplicaiton não mais referencia um objeto (e assim ele pode ser coletado pelo tempo de execução), mas de fato, através de alguma cadeia de referências, você tem uma referência a ele e, portanto, ele não pode ser coletado. Eu recomendo O artigo de Raymond Chen ligado acima, é muito esclarecedor.
 12
Author: Remus Rusanu, 2017-10-19 15:45:49

Quando a memória é atribuída a uma aplicação, a aplicação tem a obrigação de devolver essa memória ao sistema operativo para que possa ser reutilizada por outras aplicações. Uma fuga de memória ocorre quando uma aplicação não libera essa memória, impedindo-a de ser realocada.

Para o código gerido, o coletor de lixo rastreia referências aos objetos criados por uma aplicação. Para a maioria das situações o CLR irá lidar com a alocação de memória e deallocation transparente e de forma razoável em nome do processo em curso. No entanto, os desenvolvedores do. NET ainda precisam considerar a gestão de recursos como ainda existem situações em que a memória pode vazar, apesar do trabalho do coletor de lixo.

Considere o seguinte código:

Widget widget = new Widget();

A linha de código acima cria uma nova instância da classe do elemento gráfico e ao campo do elemento é atribuída uma referência a esse objecto. O GC acompanha as referências associadas a cada objecto e desalocata a memória de objetos para os quais não há referências fortes.

Vale a pena mencionar que a coleta de lixo da CLR só coletará objetos gerenciados, o código. NET pode e faz uso com frequência de recursos não geridos que não podem ser coletados automaticamente. As fugas de recursos não geridas ocorrem quando o objecto para o qual esses recursos foram afectados não consegue deslocá-los correctamente antes de a última referência a esses recursos sair do seu âmbito de aplicação, que deixa os recursos alocados, mas não referenciados e, portanto, inutilizável para a aplicação. ([8]) As Classes que referem directamente recursos não geridos devem assegurar que esses recursos sejam correctamente atribuídos. Um exemplo de fazer isso seria algo parecido com isto:
public void ManagedObject : IDisposable
{
    //A handle to some native resource.
    int* handle;

    public ManagedObject()
    {
        //AllocateHandle is a native method called via P/Invoke.
        handle = AllocateHandle();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            //deal with managed resources here
            FreeHandle(handle);
        }
    }

    ~ManagedType()
    {
        Dispose(false);
    }
}

O parâmetro disposing é falso quando é chamado de um finalizador. Isto é para evitar que os recursos gerenciados sejam usados dentro do finalizador, já que as referências gerenciadas devem ser consideradas inválidas nessa fase.

Note também que o método Dispose() chama GC.SuppressFinalize(this) o que impede que o finalizador corra para essa instância. Isto é feito porque os recursos que teriam sido desallocados no finalizador foram desallocados na chamada de eliminação fazendo uma invocação do fializador desnecessária.

Código do Cliente que faz uso de classes que lidam com recursos não gerenciados (ou qualquer classe que implementa IDisposable), deverá fazê-lo dentro de um using bloco, para garantir que o IDisposable.Dispose é chamado quando o acesso ao recurso não é mais necessário, pois isso irá cuidar tanto de recursos gerenciados e não gerenciados e, no caso do exemplo acima, garantir que uma chamada muito cara para o finalizador não é feita.

Apoligias para as minhas divagações. Vou parar agora.
 5
Author: Crippledsmurf, 2015-07-31 21:08:30
Uma fuga de memória ocorre quando o seu programa atribui dinamicamente a memória que não fica devidamente deslocada depois de a usar. Se você tem um programa que continuamente faz isso, sua fuga vai ficar maior e maior e muito em breve seu programa está tomando todo o seu RAM.
 4
Author: Nick Rolando, 2011-02-16 19:04:28

" fuga de memória "deve ser definida como" memória que é usada quando você acredita que não deve ser usada " para aplicar ao lixo coletado linguagens/períodos de execução como C#/Java.

Tradicionalmente "fuga de memória" é definida como uma memória que não está devidamente desalocada (ver link da Wikipédia em outras respostas), o que geralmente não acontece para ambientes coletados de lixo. Note que, devido a problemas com o tempo de execução, mesmo as linguagens coletadas de lixo podem vazar memória-ou seja, mesmo se JavaScript é lixo linguagem coletada, foi fácil de vazar grande quantidade de objetos JavaScript no tempo de execução JavaScript do Internet Explorer.

 4
Author: Alexei Levenkov, 2011-02-16 20:00:00