[Lazarus] Improper initialization of manged types

Anthony Walter sysrpl at gmail.com
Tue Jul 9 19:55:03 CEST 2013


Problem: Free Pascal is not properly initializing and finalizing an
interface type resulting in code being invoked for a garbage pointer. The
error is highlighted at the end.

Previously I filed a bug report on this issue and received feedback that
the bug could not be reproduced, but it's hitting me me big time when
building on 32-bit Linux (I been working on 64-bit Linux withe same same
compiler source without these problems). I'd like to post some code and get
feedback on how to fix this problem, if it is either something I am doing
or a problem with the compiler.

I have an interface type, what I would call a managed type since the
compiler ought to generate code to initialize and finalize its value, which
is used to share 1 or more contiguous floats:

  IDependencyProperty = interface
  ['{E021AD95-9985-48AB-B29F-8D25A7BBE10E}']
    function GetCount: Integer;
    function GetValue(Index: Integer): Float;
    procedure SetValue(Value: Float; Index: Integer);
    property Count: Integer read GetCount;
  end;

The interface is exposed by records TVec(n)Prop where n represents the
count or available floats. These properties are used to share float vectors
with animations/storyboards or other objects. Here is an the listing of
TVec1Prop:

  TVec1Prop = record
  private
    function GetValue: TVec1;
    procedure SetValue(Value: TVec1);
    function GetVec(Index: Integer): TVec1Prop;
    procedure SetVec(Index: Integer; const Value: TVec1Prop);
  public
    class operator Implicit(const Value: TVec1): TVec1Prop;
    class operator Implicit(const Value: TVec1Prop): TVec1;
    class operator Negative(const A: TVec1Prop): TVec1;
    class operator Positive(const A: TVec1Prop): TVec1;
    class operator Equal(const A, B: TVec1Prop) : Boolean;
    class operator NotEqual(const A, B: TVec1Prop): Boolean;
    class operator GreaterThan(const A, B: TVec1Prop): Boolean;
    class operator GreaterThanOrEqual(const A, B: TVec1Prop): Boolean;
    class operator LessThan(const A, B: TVec1Prop): Boolean;
    class operator LessThanOrEqual(const A, B: TVec1Prop): Boolean;
    class operator Add(const A, B: TVec1Prop): TVec1;
    class operator Subtract(const A, B: TVec1Prop): TVec1;
    class operator Multiply(const A, B: TVec1Prop): TVec1;
    class operator Divide(const A, B: TVec1Prop): TVec1;
    procedure Link(OnChange: TDependencyChangeNotify = nil); overload;
    procedure Link(Prop: IDependencyProperty; Index: LongInt); overload;
    procedure Unlink;
    function Linked: Boolean;
    function Equals(const A: TVec1Prop): Boolean;
    function Same(const A: TVec1Prop): Boolean;
    property X: TVec1Prop index 0 read GetVec write SetVec;
    property Value: TVec1 read GetValue write SetValue;
    property Vec[Index: Integer]: TVec1Prop read GetVec write SetVec;
  private
    FProp: IDependencyProperty;
    case Boolean of
      True: (FIndex: LongInt);
      False: (FValue: TVec1);
  end;

Part of the implementation looks like this with an example of the ERROR in
comments:

{ TVec1Prop }

class operator TVec1Prop.Implicit(const Value: TVec1Prop): TVec1;
begin
  Result := Value.Value;
end;

class operator TVec1Prop.Implicit(const Value: TVec1): TVec1Prop;
begin
  // ERROR: WriteLn(UIntPtr(Result.FProp)); writes out a random memory
location
  // ERROR: Result.FProp should be nil already but it is not
  Result.FProp := nil; // ERROR: Code is generated which attempts to call
release on random garbage
  Result.FIndex := 0;
  Result.FValue := Value;
end;

function TVec1Prop.GetValue: TVec1;
begin
  if FProp = nil then
    Result := FValue
  else
    Result := FProp.GetValue(FIndex);
end;

procedure TVec1Prop.SetValue(Value: TVec1);
begin
  if FProp = nil then
    FValue := Value
  else
    FProp.SetValue(Value, FIndex);
end;

The problem is happening in a lot of places which use my TVec(n)Prop types,
resulting in many AV errors, but again only when I am recompiling my demo
programs on 32-bit Linux (with the same compiler source). For example I
have a list of TVec1Prop, when I clear the list I am getting AV errors due
to some items not being finalized correctly.

What should I do?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20130709/04506e79/attachment-0002.html>


More information about the Lazarus mailing list