2010-09-03 12 views
3

J'utilise un ancien moteur de script qui n'est plus supporté par ses créateurs, et qui a des problèmes avec les fuites de mémoire. Il utilise une fonction écrite en ASM pour appeler des scripts vers des fonctions Delphi, et renvoie le résultat sous la forme d'un entier puis passe cet entier en tant que paramètre non typé à une autre procédure qui le traduit en le type correct.Comment arrêter cette fuite de mémoire Variant?

Cela fonctionne très bien pour la plupart des choses, mais lorsque le type de retour de la fonction Delphi était Variant, il perd de la mémoire car la variante n'est jamais éliminée. Est-ce que quelqu'un sait comment je peux prendre un paramètre non typé contenant une variante et m'assurer qu'il sera éliminé correctement? Cela impliquera probablement un assemblage en ligne.

procedure ConvertVariant(var input; var output: variant); 
begin 
    output := variant(input); 
    asm 
    //what do I put here? Input is still held in EAX at this point. 
    end; 
end; 

EDIT: En réponse à la question de Rob Kennedy dans les commentaires:

conversion AnsiString fonctionne comme ceci:

procedure VarFromString2(var s : AnsiString; var v : Variant); 
begin 
    v := s; 
    s := ''; 
end; 

procedure StringToVar(var p; var v : Variant); 
begin 
    asm 
    call VarFromString2 
    end; 
end; 

Cela fonctionne très bien et ne produit pas de fuites de mémoire. Lorsque j'essaie de faire la même chose avec une variante que le paramètre d'entrée et affecter le Null d'origine sur la deuxième procédure, les fuites de mémoire se produisent encore.

Les variantes contiennent principalement des chaînes - le script en question est utilisé pour générer XML - et elles y sont arrivées en affectant une chaîne Delphi à une variante de la fonction Delphi que ce script appelle. (Changer le type de retour de la fonction ne fonctionnerait pas dans ce cas.)

+0

Comment le Variant est-il entré dans ce premier paramètre au départ? Quel type de variable a été utilisé pour le paramètre réel? Quand vous dites que cela fonctionne pour "la plupart des choses", cela inclut-il AnsiString? L'élimination de cela devrait être similaire à l'élimination des variantes. –

+0

@Rob: Mise à jour avec les réponses à vos questions. –

+0

J'aimerais toujours savoir comment le premier paramètre est peuplé. Autrement dit, comment 'ConvertVariant' et' StringToVar' sont appelés? C'est * la Variante du * premier * paramètre qui fuit, non? –

Répondre

3

Avez-vous essayé le même tour qu'avec la chaîne, sauf qu'avec un Variant, vous devriez mettre UnAssigned au lieu de Null pour le libérer, comme vous avez fait s := ''; pour la chaîne. Et en passant, l'une des seules raisons que je peux penser à cela, c'est de libérer explicitement les chaînes, les variantes, etc ... lors de l'utilisation de ThreadVar.

+0

... ou si le code fait des choses de bas niveau qui interfèrent avec la capacité du compilateur à générer automatiquement du code de nettoyage. –

+0

J'ai essayé cela, et je continue à voir l'utilisation de la mémoire augmenter chaque fois que je cours. C'est la seule indication que je dois tester, car les variantes ne sont pas allouées par FastMM et n'apparaissent pas dans le rapport de fuite de mémoire. Mais cela diminue considérablement, ce qui signifie que cela aide et qu'il y a quelque chose d'autre qui fuit aussi. :( –