Pergunta

Eu tive esse bug desagradável que desapareceu no passado, mas agora, depois de algum tempo ele retornou.

I têm dois objectos tsam (derivado de TPersistent) criado e carregado para um objecto TAsmJob (derivado de TObjectList).

Durante a execução, uma forma cria um TStringGrid e, em seguida, o AsmJob que cria os dois objetos SAM (e carregar alguns dados do disco em cada uma delas). O AsmJob também é atribuído à rede. Quando o formulário é destruída, a grade cuida do AsmJob por libertá-la, o que libera os objetos tsam. Aqui está o problema:. O primeiro objeto é liberado withot problemas, mas o segundo morre quando seu método herdado (em Destruir destructor) é chamado

Eu uso FreeAndNil em todo o programa para libertar os objetos. Os objetos tsam não são NIL !!!!! Então, esta é a primeira tentativa de libertar os objetos. Mesmo os dados dentro dos objetos é consistente.

A espinha dorsal dos olhares programa como este:

**Create:**

Form -> StringGrid
     -> AsmJob -> Sam1, Sam2
StringGrid.AsmJob:= AsmJob;


**Free:**

Form -> StringGrid -> AsmJob -> Sam1, Sam2

Eu realmente não entendo onde eu tentar dobrar-free ou substituir o objeto depois que ele foi liberado.


edit:

Alguns dos erros que eu tenho:

  • FastMM detectou um erro durante uma bloco livre operação de varredura. FastMM detectou que um bloco tem sido modificado depois de ser libertado.

  • FastMM detectou um erro durante uma bloco livre operação de varredura. O bloco cabeceamento foi corrompido.

Detalhe:

The current thread ID is 0x19C, and the stack trace (return addresses) leading to this error is: 
402E77 [System][@FreeMem] 
4068DC [System][@DynArrayClear] 
405E2D [System][@FinalizeArray] 
405D31 [System][@FinalizeRecord] 
40432F [System][TObject.CleanupInstance] 
404272 [System][TObject.FreeInstance] 
404641 [System][@ClassDestroy] 
4D313E [UnitSam.pas][TSam.Destroy][297] 
4042BF [System][TObject.Free] 
4149ED [SysUtils][FreeAndNil] 
4D9C0A [UnitAsmJob.pas][UnitAsmJob][TAsmJob.Destroy][180]  

Eu tenho todas as opções de "depuração" habilitado no IDE, incluindo o "Range Check". Além disso, o FastMM4 está definido para o modo de depuração agressivo super. Sem FastMM ou fora do depurador o programa funciona muito bem - mas ainda assim, eu sei que isso não significa que o erro não está mais lá. Na verdade, ele trabalhou (provavelmente) por mais de um um ano, até que eu tenha instalado FastMM.


edit:

Graças a todos. Não estou me sentindo Eu estou movendo um pouco na direção boa.

A estrutura do programa é mais complicado I oferecido apenas a espinha dorsal para manter o post original pequeno. Mas o que o Parreira, ele já ficou maior :) Então, esses objetos tsam são usados ??para carregar os dados do disco. Um arquivo em cada objeto. Eles estão fazendo também alguma validação processamento e dados. Para cada um destes tsam I também têm um objecto gráfico que mostra no ecrã (graficamente) os dados contidos nos objetos tsam. Cada linha no TStringGrid também mostram os dados em tsam, mas textualmente.

Uma pergunta que eu tenho: se eu quebrar o programa em partes menores para descobrir onde está o erro, o erro ainda aparecerá? Ou é possível só aparecem nessa configuração particular?


resposta à pergunta "como é que o AsmJob são designados para TStringGrid para que o TStringGrid destrói a AsmJob, você pode nos mostrar?"

MyGrid = TStringGrid
  public 
    AsmJob: TAsmJob; 
  end; 

, em seguida, em algum lugar no TForm.Create (a forma que contém o Grid), eu faço

MyGrid.AsmJob=AsmJob; 

e no processo de destruição do MyGrid eu faço:

begin 
  FreeAndNil(AsmJob); 
  inherited 
end;
Foi útil?

Solução

Isto significa erro que seu código corrompido estruturas do gerente de memória interna. Sua pilha de chamadas representa o ponto, quando MM detectado isso. Isto não é caminho de erro ou qualquer coisa relacionada a ele. O erro real acontece antes deste momento. Ele pode ou não estar relacionada com classes mencionadas.

Você deve tentar usar "erros verificação de intervalo" opção (don 't se esqueça de fazer Build, não compilar) e FastMM no modo de depuração completo (com CheckHeapForCorruption, CatchUseOfFreedInterfaces è opções DetectMMOperationsAfterUninstall habilitado) .

Você também pode ligar FullDebugModeScanMemoryPoolBeforeEveryOperation variável global, para obter um erro quase imediatamente após problema ocorre, mas esta opção retarda o seu execução MUITO.

Provavelmente a melhor opção é chamada ScanMemoryPoolForCorruptions periodicamente. Chamá-lo em um lugar. Tenho um erro? Chamá-lo mais cedo. Ainda tenho um erro? Chamá-lo mais cedo novamente. Nenhum erro? Seu problema se senta em algum lugar entre essas últimas chamadas. Agora você pode usar FullDebugModeScanMemoryPoolBeforeEveryOperation variável para obter localização precisa. Basta ligá-lo apenas na área deste código e desligá-lo logo depois.

Há um erro muito semelhante: "FastMM detectou que um bloco foi modificado depois de ser libertado". Neste caso suas modifica código não estruturas internas, mas outras de memória, o que não é usado em tudo ( "memória livre").

BTW, o erro não é double-livre! Se esta é uma chamada double-free, FastMM irá dizer-lhe que explicitamente (é fácil de detectar, como você está tentando libertar um bloco de memória não-utilizados ou não-existente): "Uma tentativa foi feita para um livre / realocar bloco não alocado".

Outras dicas

Um cabeçalho do bloco ficar corrompido geralmente significa algo de se substituir a memória, geralmente fazendo algum tipo de operação insegura. Você está usando ponteiros crus ou código de montagem em qualquer de suas tarefas? Além disso, se você tem a verificação de intervalo e verificação de limites desligado, tente ligá-las e reconstrução. Eles podem ajudar a pegar um monte de este tipo de problema.

Pode haver um lugar de corrida lógica no código onde um objeto está sendo escrito como ele está sendo liberado. Adicionar NULL-cheques e outros mecanismos de IPC (listas de bloqueio, etc.) para se certificar de que não é o caso.

Outra opção poderia ser a subclasse o código para adicionar o registo a ele -. E verificar se os objetos estão sendo sequencialmente acessados ??

Um par de coisas e eu estou perguntando porque eu não posso ver o seu código.

Dado o seguinte código:

procedure TForm1.FormCreate(Sender: TObject);
var
   wObjLst : TObjectList;
begin
   wObjLst := TObjectList.Create;
   try
      wObjlst.OwnsObjects := true;
      wObjlst.Add(TPersistent.Create);
      wObjlst.Add(TPersistent.Create);
   finally
      freeandnil(wObjlst);
   end;
end;

Isso funciona com o erro.

estado Você que

No momento da execução, uma forma cria um TStringGrid e então o AsmJob que cria estes dois objectos SAM (e carregar alguns dados do disco em cada um dos eles). O AsmJob também é atribuído à rede. Quando a forma é destruída, Grid cuida do AsmJob por libertá-la, o que libera o tsam objetos. Aqui está o problema: o primeiro objeto é liberado withot problemas mas as segundas matrizes quando um seu método herdado (em destruir destructor) é chamado.

A minha primeira pergunta é como é que o AsmJob são designados para TStringGrid para que o TStringGrid destrói a AsmJob, você pode mostrar-nos?

Em segundo lugar, por que criar um descendente de TObjectList para obtê-lo para armazenar dois objetos e, em seguida, livre libertá-los, em vez de criá-los você mesmo e deixar o TObjectList destruí-los como mostrado acima.

A outra coisa é tentar baixar o pacote FastMM4 completa de fastmm.sourceforge.net , instalá-lo e usar a dll fulldebug traçar exatamente o objeto está falhando. Você e eu estamos assumindo que é um dos SAM objetos e pode ou não ser.

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