[fpc-pascal] Sigsegv with refcounting interface

Joao Morais jcmoraisjr at gmail.com
Thu Mar 7 12:29:31 CET 2013


Hello list, what's the problem with "RoundThree" procedure (below)?
Here it raises a sigsegv trying to read an internal field. The
difference from "RoundTwo" is that I create an implementation of the
interface within the first param of tinterfacedlist.add method.

Same problem with fpc 2.6.2 and 2.7.1 (from two days ago), i386-win32.

Joao Morais

==============

program project1;

{$mode objfpc}{$H+}

uses
  heaptrc,
  sysutils,
  Classes;

type
  iintf = interface
  ['{9E08FFD2-5AC4-4AE7-B2C6-703D62A10F16}']
    function RefCount: Integer;
  end;

  { tintf }

  tintf = class(TInterfacedObject, iintf)
  public
    constructor Create;
    destructor Destroy; override;
    function RefCount: Integer;
  end;

{ tintf }

constructor tintf.Create;
begin
  inherited Create;
  writeln('tintf "', PtrUInt(Self) ,'" created');
end;

destructor tintf.Destroy;
begin
  writeln('tintf "', PtrUInt(Self) ,'" destroyed');
  inherited Destroy;
end;

function tintf.RefCount: Integer;
begin
  Result := inherited RefCount;
end;

procedure RoundOne;
var
  vintf: TInterfaceList;
  v1: iintf;
begin
  writeln;
  writeln('Round one');
  writeln('---------');
  vintf := TInterfaceList.Create;
  try
    writeln('creating and adding...');
    vintf.Add(tintf.create);
    writeln('retrieving to v1...');
    if vintf[0].QueryInterface(iintf, v1) = S_OK then
    begin
      writeln('trying to write v1.RefCount...');
      writeln('counting: ', v1.RefCount);
    end else
      writeln('problem');
    v1 := nil;
  finally
    FreeAndNil(vintf);
  end;
end;

procedure RoundTwo;
var
  vintf: TInterfaceList;
  v1, v2: iintf;
begin
  writeln;
  writeln('Round two');
  writeln('---------');
  vintf := TInterfaceList.Create;
  try
    writeln('creating...');
    v2 := tintf.Create;
    writeln('adding...');
    vintf.Add(v2);
    writeln('typecasting to v1...');
    v1 := iintf(vintf[0]);
    writeln('trying to write v1.RefCount...');
    writeln('counting: ', v1.RefCount);
    v1 := nil;
    v2 := nil;
  finally
    FreeAndNil(vintf);
  end;
end;

procedure RoundThree;
var
  vintf: TInterfaceList;
  v1: iintf;
begin
  writeln;
  writeln('Round three');
  writeln('-----------');
  vintf := TInterfaceList.Create;
  try
    writeln('creating and adding...');
    vintf.Add(tintf.Create);
    writeln('typecasting to v1...');
    v1 := iintf(vintf[0]);
    writeln('trying to write v1.RefCount...');
    writeln('counting: ', v1.RefCount);
    v1 := nil;
  finally
    FreeAndNil(vintf);
  end;
end;

begin
  RoundOne;
  RoundTwo;
  RoundThree;
end.



More information about the fpc-pascal mailing list