3
votes

I'm using an old script engine that's no longer supported by its creators, and having some trouble with memory leaks. It uses a function written in ASM to call from scripts into Delphi functions, and returns the result as an integer then passes that integer as an untyped parameter to another procedure that translates it into the correct type.

This works fine for most things, but when the return type of the Delphi function was Variant, it leaks memory because the variant is never getting disposed of. Does anyone know how I can take an untyped parameter containing a variant and ensure that it will be disposed of properly? This will probably involve some inline assembly.

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: Responding to Rob Kennedy's question in comments:

AnsiString conversion works like this:

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;

That works fine and doesn't produce memory leaks. When I try to do the same thing with a variant as the input parameter, and assign the original Null on the second procedure, the memory leaks still happen.

The variants mostly contain strings--the script in question is used to generate XML--and they got there by assigning a Delphi string to a variant in the Delphi function that this script is calling. (Changing the return type of the function wouldn't work in this case.)

1
How did the Variant get into that first parameter initially? What variable type was used for the actual parameter? When you say it works for "most things," does that include AnsiString? Disposal of that should be similar to disposal of Variants.Rob Kennedy
@Rob: Updated with answers to your questions.Mason Wheeler
I'd still like to know how the first parameter is populated. That is, how do ConvertVariant and StringToVar get called? It is the Variant in the first parameter that's leaking, right?Rob Kennedy
Mason, you tried using the function varclear ? docwiki.embarcadero.com/VCL/en/System.VarClearRRUZ
I suspect your "procedure StringToVar;" could just be: "asm jmp VarFromString2 end;".PhiS

1 Answers

3
votes

Have you tried the same trick as with the string, except that with a Variant, you should put UnAssigned instead of Null to free it, like you did s := ''; for the string.

And by the way, one of the only reasons I can think of that requires to explicitly free the strings, Variants, etc... is when using some ThreadVar.