Pergunta

Eu herdei um aplicativo IntraWeb que tinha um arquivo de texto 2MB de vazamentos de memória conforme relatado por FastMM4. Eu tenho-o para 115 instâncias de uma classe vazamento de 52 bytes.

Uma descrição breve do mau ator é:

TCwcBasicAdapter = class(TCwcCustomAdapter)  
  protected  
    FNavTitleField: TField;  
    function GetAdapterNav(aDataSet: TDataSet): ICwcCDSAdapterNav; override;  
  public  
    constructor Create(aDataSource: TDataSource; aKeyField, aNavTitleField: TField; aMultiple: boolean);  
  end;  

e a interface é:

  ICwcCDSAdapterNav = interface(IInterface)  

Am I latindo para a árvore errada, uma vez que a propriedade é referência contada? Existem quaisquer circunstâncias em que a propriedade de interface poderia manter a classe de ser destruído?

Aqui está a implementação do método acima:

function TCwcBasicAdapter.GetAdapterNav(aDataSet: TDataSet): ICwcCDSAdapterNav;
var
  AdapterNav: TCwcCDSAdapterNavBase;
begin
  result := nil;
  if Assigned(aDataSet) then begin
    AdapterNav := TCwcCDSAdapterNavBasic.Create(aDataSet, FKeyField.Index, FNavTitleField.Index);
    try
      AdapterNav.GetInterface(ICwcCDSAdapterNav, result);
    except
      FreeAndNil(AdapterNav);
      raise;
    end;
  end;
end;

com a classe declarada como:

TCwcCDSAdapterNavBase = class(TInterfacedObject, ICwcCDSAdapterNav)
Foi útil?

Solução

FastMM deve dar-lhe o que é vazado e onde ele foi criado.
Isso ajudaria limitando-o ao verdadeiro culpado: quem está vazando o

Eu não tenho certeza do que realmente a sua pergunta é?
Seu código é incompleta ou não aquele em questão: a sua classe não tem uma propriedade de interface nem um campo privado Interface, apenas um método que retorna uma interface, que é inofensivo

.

Editar :. Sem ver o código do seu ICwcCDSAdapterNav implementação de Object, não podemos dizer se ele é realmente referência contada
Se você não descerá do TInterfacedObject , chances são que não é referência contada e que você não pode contar com isso automagicamente libertação ...

Você pode querer dar uma olhada nesta sessão CodeRage 2 : Luta vazamentos de memória para Dummies . É principalmente mostra como usar FastMM para prevenir / detectar vazamentos de memória em Delphi. Era para D2007, mas ainda é relevante para outras versões.

Outras dicas

Você tem algumas boas respostas até agora sobre como FastMM funciona. Mas, quanto a sua pergunta real, sim, objetos interligados pode vazar de duas maneiras diferentes.

  1. Interfaces são apenas se os objetos que pertencem implementaram contagem de referência em seus métodos _AddRef e _Release contou-referência. Alguns objetos não.
  2. Se você tem referências de interface circular, (interface de 1 referências de interface 2, que as referências de interface 1), então a contagem de referência nunca vai cair para 0 sem alguns truques especiais de sua parte. Se este for o seu problema, eu vou encaminhá-lo para post recente de Andreas Hausladen sobre o assunto.

Se você está vazando 115 instâncias dessa classe, então é essa classe que está a ser vazado. A memória ocupada por essa classe, não a memória ocupada pelas coisas que ela se refere, está sendo vazado. Em algum lugar, você tem 115 casos de TCwcBasicAdapter que você não está liberando.

Além disso, propriedades não armazenar dados, não importa o que eles estão interfaces ou algum outro tipo. Somente os campos ocupam memória (junto com algum espaço escondido os aloca compilador em nome da classe).

Então, sim, você está latindo para a árvore errada. Sua fuga de memória é em outro lugar. Quando FastMM diz que você tem um vazamento de memória, não é também dizer-lhe onde cada instância vazou foi alocado. Ele tem essa capacidade; você pode precisar ajustar alguns símbolos condicional-compilation para habilitar esse recurso.

Com certeza não é única instâncias dessa classe que estão vazando, no entanto. FastMM também deve relatar algumas outras coisas vazando, como instâncias da classe ou classes que implementam a interface.


Com base na função que você adicionou, comecei a suspeitar que ele é realmente TCwcCDSAdapterNavBase que está vazando, e que poderia ser por causa da maneira atípica que você usa para criá-la. O manipulador de exceção em GetAdapterNav nunca correr? Eu duvido; TObject.GetInterface levanta nunca mais explicitamente uma exceção. Se o objeto não suporta a interface, ele retorna False. Tudo o que manipulador de exceção pode pegar são coisas como violação de acesso e operações ilegais, o que você realmente não deveria estar pegando lá de qualquer maneira.

Você pode implementar essa função mais diretamente como esta:

if Assigned(FDataSet) then
  Result := TCwcCDSAdapterNavBase.Create(...);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top