Když nemůžeš najít proč se to uvolňuje dvakrát, tak jednoduchá finta (ale není to elegantní řešení, leč funguje):
if Assigned (MujObjekt) then begn MujObjekt.Free (); MujObjekt := nil end;
nebo já používám na to proceduru:procedure MyFreeAndNil (var AObject: TObject);
begin if Assigned (AObject) then begin AObject.Free (); AObject := nil end
end;
// pak voláme jen:
MyFreeAndNil (MujObjekt);
Pro přesnější radu bych musel program vidět. Nemusí (jak se mi zdá) jít o problém dědičnosti, ale zapouzdřenosti (to je rozdíl!) Kontejnerový objekt by měl sám uvolnit uvnitř přidané objekty, ale musí je znát, proto zadáváme do konstruktoru objekt majitele (obvykle parametr AOwner). Konstruktor pak zajistí, aby kontejnerový objekt (třeba formulář) sám uvolnil vnořené objekty (tlačítka, canvas, textová pole....).