2015-02-19 13 views
6

Il TTaskbar di Embarcadero ha una perdita di memoria. Poiché ho abbandonato questo controllo sul mio modulo, FastMM segnala una perdita ogni volta che chiudo l'app.Perdita di memoria TTaskBar

ho cercato di disattivare FastMM con questo codice:

procedure TMainForm.FormCreate(Sender: TObject); 
begin 
fastmm4.RegisterExpectedMemoryLeak(Taskbar); 
end; 

ma non funzionerà. Come registrare questa perdita?


un blocco di memoria è trapelato. La dimensione è: 100

Questo blocco è stato assegnato dal filo 0xC64, e la traccia dello stack (ritorno indirizzi) al momento era: 406A52 409A7B 409CAC 4283A0

[System.SysUtils] [Sistema] [System.SysUtils .FmtStr] 409CC6 40D775 7628A65F
[funzione sconosciuta a StretchDIBits] 7731594E
[funzione sconosciuta a RtlpNtMakeTemporaryKey] 7731594E
[funzione sconosciuta a RtlpNtMakeTemporaryKey] 773168F8
[funzione sconosciuta a RtlpNtMakeTemporaryKey] 773168DC
[funzione sconosciuta a RtlpNtMakeTemporaryKey]

Il blocco è attualmente utilizzato per un oggetto di classe: UnicodeString
Il numero di allocazione è: 2209

Un blocco di memoria è stata soffiata. La dimensione è: 36

Questo blocco è stato assegnato dal filo 0xC64, e la traccia dello stack (ritorno indirizzi) al momento era: 406A52 407D43 40846A 42CD40
[System.SysUtils] [Sistema] [System.SysUtils. Exception.CreateFmt] 5DEDD7
[System.Win.TaskbarCore] [System.Win] [System.Win.TaskbarCore.TTaskbarBase.UpdateTab] 610F00
[Vcl.Taskbar] [Vcl] [Vcl.Taskbar.CheckMDI] 5DF39F
[System.Win.TaskbarCore] [System.Win] [System.Win.TaskbarCore.TTaskbarBase.ApplyTabsChanges] 610DB8
[Vcl.Taskbar] [Vcl] [Vcl.Taskb ar.TCustomTaskbar.Initialize] 5EB044
[Vcl.Forms] [Vcl] [Vcl.Forms.TApplication.Run] 62573A
[MinimalTemplate.dpr] [MinimalTemplate] [MinimalTemplate.MinimalTemplate] [26]

Il blocco è attualmente utilizzato per un oggetto di classe: ETaskbarException
Il numero di allocazione è: 2207

Questa applicazione ha perso memoria. Le perdite piccolo blocco sono (escludendo perdite attesi registrate dal puntatore):

21 - 36 bytes: ETaskbarException x 1
85 - 100 byte: UnicodeString x 1
[Vcl.Forms] [Vcl] [Vcl.Forms .TCustomForm.SetVisible] 5F5010

+0

non riesco a riprodurre qui. OK ora posso vedere dove è la perdita. È in 'TTaskbarBase.UpdateTab'. È anche un po 'scioccante! –

+0

Non penso che sarà facile affrontarlo. Risolvere il problema è probabilmente la strada da seguire. Non posso più fare a meno di una riproduzione. Tuttavia, è necessario inviare una segnalazione di bug a emba. Creare un'eccezione ma non riuscire a risolverlo? !!! –

+0

Progetto di replica qui: http://www.filedropper.com/repro_1 – Ampere

risposta

10

La memoria è trapelato in questo codice da System.Win.TaskbarCore:

procedure TTaskbarBase.UpdateTab; 
var 
    LpfIsiconic: LONGBOOL; 
    LHandle: HWND; 
    LFlags: Integer; 
begin 
    if FTaskbarIsAvailable then 
    begin 
    LHandle := GetFormHandle; 
    if not FRegistered and TaskBar.RegisterTab(LHandle) then 
    begin 
     TaskBar.SetTabOrder(LHandle); 
     TaskBar.SetTabActive(LHandle); 
     FRegistered := True; 
    end 
    else 
     ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]); 
.... 

La riga finale crea un'eccezione, e poi non fa nulla con esso. L'eccezione e la stringa che possiede sono trapelate. Come riportato da FastMM.

È possibile registrare questi oggetti come fuoriusciti se è possibile ottenere i loro indirizzi. Tuttavia, non puoi farlo. Non c'è modo di fare riferimento a questo oggetto di eccezione.

Se si deve semplicemente evitare questa perdita segnalata erroneamente, e ha senso che lo si vorrebbe, quindi sarà necessario includere una versione fissa di System.Win.TaskbarCore nel progetto. Crea una copia di quel file e aggiungila al tuo progetto. Quindi modificare il codice per correggere l'errore. La mia ipotesi è che sarebbe andata così:

if not FRegistered then 
begin 
    if TaskBar.RegisterTab(LHandle) then 
    begin 
    TaskBar.SetTabOrder(LHandle); 
    TaskBar.SetTabActive(LHandle); 
    FRegistered := True; 
    end 
    else 
    raise ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]); 
end; 

Chiaramente questo deve essere segnalato a Embarcadero. Ti suggerisco di inviare una segnalazione di bug.


Un altro modo per aggirare questo è cercare di evitare l'esecuzione della linea fasulla. Credo che se si rimuove questa riga dal file DFM, si dovrebbe evitare la linea fasullo, e quindi evitare la perdita:

Visible = True 

sufficiente rimuovere quella linea, sembra essere il grilletto.

Nota che l'ho risolto tagliando il progetto fino alla sua struttura. Per riprodurre il problema è il file minimo DFM necessario:

object Form1: TMainForm 
    Visible = True 
    object Taskbar1: TTaskbar 
    end 
end 

E con questo file DFM non ci siano perdite:

object Form1: TMainForm 
    object Taskbar1: TTaskbar 
    end 
end 

Riducendo il progetto fino al minimo indispensabile, ero in grado di trovare il grilletto. Non posso sottolineare abbastanza quanto sia preziosa questa tecnica di minimizzare una riproduzione.


Grazie a Remy per trovare il report di controllo di qualità per questo errore: QC#128865

+0

Ovviamente non ci sono riusciti a "sollevare" quell'eccezione. – TLama

+0

@TLama Beh, non proprio. Se 'FRegistered' è' True', non dovrebbe essere sollevato. Aggiungerò un aggiornamento su cosa ritengo possa essere la correzione. –

+0

Ho affrontato solo il problema di perdita, che è chiaramente un'eccezione che avrebbe dovuto essere sollevata. – TLama