Title: pointer to variant - caution!
(deutsche Version siehe unten)
I just ran across this in some of my old code and thought I'd share it with you:
Consider the following (simplified code):
function CreateVariantPtr(_Value: variant): pVariant;
begin
GetMem(Result, SizeOf(Variant));
Result^ := _Value;
end;
Seems pretty simple, doesn't it? Anybody who can spot the bug?
I got spurious access violations in the line
Result^ := _Value;
Ok, the reason:
Memory allocated with GetMem is not initialised, so the "Variant" pointed to by
Result contains some random data, for example something that might represent a
variant type which requires some finalisation when the variant is changed,
lets say a variant array of some sort. But this finalisation won't work
because the content is just some random garbage, and sometimes I was lucky
(I mean that!) and got an access violation that allowed me to spot the error.
The fix:
function CreateVariantPtr(_Value: variant): pVariant;
begin
GetMem(Result, SizeOf(Variant));
Initialize(Result^);
Result^ := _Value;
end;
{***********--- deutsch ---***********************}
Mir ist gerade folgendes in ein alten Sourcen aufgefallen und ich dachte,
das interessiert den einen oder anderen..
Folgender Code (vereinfacht):
function CreateVariantPtr(_Value: variant): pVariant;
begin
GetMem(Result, SizeOf(Variant));
Result^ := _Value;
end;
Sieht ziemlich simpel aus, oder? Kann jemand den Bug finden?
Ich bekam manchmal Access Violations in der Zeile.
Result^ := _Value;
Der Grund:
Wenn man Speicher mit GetMem anfordert, so wird dieser nicht initialisiert,
d.h. das der "Variant", auf den Result zeigt, voellig zufaelligen Inhalt hat,
es koennte z.B. eine Variant-Typ sein, der, wenn er ueberschrieben wird,
irgendwie freigegeben werden muss, z.B. ein Variant Array.
Aber das Freigeben wuerde fehlschlagen, denn es ist ja nicht wirklich ein Variant
Array sondern nur Speichermuell, der zufaellig so aussieht wie ein solches.
Und ich hatte das Glueck (und ich meine Glueck) dass ich eine Access Violation bekam,
die mich auf diesen Fehler hinwies (die Alternative ist, dass der Freigabecode irgendwo
im Speicher rumbastelt und dabei moeglicherweise wichtige Daten veraendert,
ohne dass ich das merke, so mit der am schwierigsten zu findende Bug, den es gibt).
Der Bugfix:
function CreateVariantPtr(_Value: variant): pVariant;
begin
GetMem(Result, SizeOf(Variant));
Initialize(Result^);
Result^ := _Value;
end;