2011-02-15 7 views
7

Actualización: Los cambios para introducir estilos VCL en XE2 han eliminado la pérdida de memoria. Así que supongo que fue involuntario después de todo.¿Por qué Themes.pas filtra el singleton TThemeServices cuando se vincula a un archivo DLL


Me encontré con una fuga de memoria VCL hoy, en Themes.pas. Solo ocurre para las DLL. El código de unidad de finalización es tan así:

finalization 
    if not IsLibrary then 
    InternalServices.Free; 

InternalServices es un producto único que se crea en la demanda cuando se llama a la función ThemeServices. Muchas DLL no tienen UI, por lo que nunca crees este singleton. Sin embargo, tengo un complemento COM para Excel que da como resultado esta manifestación de fugas.

La fuga no me molesta particularmente porque esta DLL nunca se carga y descarga repetidamente del mismo proceso. Y sé cómo podría arreglar la fuga usando la variable global ThemeServicesClass.

Mi pregunta, sin embargo, es preguntar si alguien puede explicar por qué este código es la forma en que es. Parece bastante deliberadamente codificado de esta manera. Por mi vida no puedo encontrar una explicación para esta fuga intencional.

+0

que tiene varias QC informes con el estado abierto: 90368, 84990, 66013 –

+4

@Sertac Usted sabe que yo tenía la intención de presentar una Informe de control de calidad i f No pude encontrar una explicación. El código parecía tan intencional que no me imaginé que sería un error y nunca consideré buscar control de calidad. Debo decir que las respuestas a esos informes de control de calidad son demasiado deprimentemente familiares. Los remitentes presentan las líneas del código fuente de VCL que flaquean abiertamente, y Tomohiro Takahashi pide un proyecto de muestra para reproducirlo. ¡Lo pone fuera de la presentación de informes! –

+0

Eso, y otras formas que lo desaniman ... Conozco la sensación ... Por cierto, algunos de los reporteros/comentaristas han configurado 'IsLibrary' como falso para una solución alternativa, lo que me hace sospechar si hay alguna buena razón para código en absoluto. –

Respuesta

5

Una explicación es que la sección de finalización de la unidad se ejecuta mientras el cerradura del cargador OS está activo. Durante ese tiempo, existen restricciones significativas sobre lo que se permite hacer un archivo DLL sin poner en riesgo el interbloqueo.

+0

Ah, soy consciente del problema con el bloqueo del cargador, y me tomo algunos problemas para evitarlo, pero no lo había recordado al tratar de explicar esto. Gracias, echaré un vistazo al código del destructor y veré si hace algo que podría ser un problema. –

+0

El destructor llama a 'CloseThemeData' para cada elemento temático que se ha guardado en caché, y luego llama a' UxTheme.FreeThemeLibrary'. Pensé que podría ser un problema, pero UxTheme se complace en llamar a 'FreeThemeLibrary' en su finalización, por lo que no puede ser. No hay miembros de clase de tipos administrados (por ejemplo, interfaces). –

5

Nos encontramos con este mismo problema también. Esto es lo que estamos haciendo actualmente para prevenir la fuga en nuestros proyectos:

  1. en la DLL .dpr archivo de añadir temas a la sección de usos.

  2. añadir lo siguiente al limpiar la fuga en el cierre:

    procedure DLLEntryProc(EntryCode: integer); 
    begin 
        case EntryCode of 
        DLL_PROCESS_DETACH: 
        begin 
        ThemeServices.Free; 
        end; 
        DLL_PROCESS_ATTACH: 
        begin 
        end; 
        DLL_THREAD_ATTACH: 
        begin 
        end; 
        DLL_THREAD_DETACH: 
        begin 
        end; 
        end; 
    end; 
    
    begin 
        {$IFDEF DEBUG} 
        ReportMemoryLeaksOnShutdown := True; 
        {$ENDIF} 
        DllProc := @DLLEntryProc; 
    end. 
    
0

En la misma idea de que debe haber una buena razón para dejar que escape (Indy fugas de un par de cosas a propósito así, o al menos lo que solía) prefiero ignorarlo, así:

{$I FastMM4Options.inc} 
... 
{$IFDEF EnableMemoryLeakReporting} 
    if IsLibrary then// ThemeServices is leaked when created in a DLL. 
    RegisterExpectedMemoryLeak(ThemeServices); 
{$ENDIF} 
Cuestiones relacionadas