[fpc-pascal] TInterfacedObject destructor reentrance bug

2017-07-15 Thread African Wild Dog
Hello,

I have found a bug in the TInterfacedObject.

Better than explaining is to examine and execute the code below.
When executing the code below the destructor of the class
TCustomDestructorClass is called infinitely.
This is due to calling the procedure Foo inside the destructor of
TCustomDestructorClass, whhich causes the _addRef and _Release methods to
be called again. As the reference count reaches zero again, this triggers
the calling of the destructor again e and so the cycle will repeat
infinitely.

I think one solution would be the _Release method to check if the instance
is already being destroyed before calling the destructor of the class
(Destroy method). Currently the method only checks if the reference count
reaches zero.

 CODE BEGIN =

program interfaced_object_error_2;

type

  { TCustomDeestructorClass }

  TCustomDestructorClass = class(TInterfacedObject)
  public
destructor Destroy; override;
  end;

var
  DestrcutorCount: Integer = 0;
  CustomRef: IInterface;

procedure Foo(Value: IInterface);
begin
  if Value <> nil then
Inc(DestrcutorCount);
end;

{ TCustomDeestructorClass }

destructor TCustomDestructorClass.Destroy;
begin
  Foo(Self);
  inherited Destroy;
end;

begin
  CustomRef := TCustomDestructorClass.Create;
  CustomRef := TCustomDestructorClass.Create; // Forces execution of
destructor
end.

=== END ===
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Convert to int64 note

2017-07-15 Thread Santiago A.
El 14/07/2017 a las 17:19, ja...@productionautomation.net escribió:
>> If you declare Last_GS as int64, you should not get the warning.
> I declared both Last_GS and G_End as int64, leaving Max_Program_to_Display as 
> a word and still get the warning.  If I also make Max_Program_to_Display 
> int64, then I do not get the warning.   I believe it's due to the -1. If 
> Max_Program_To_Display was a 0 then subtracting 1 from it would be out of 
> range from a word for that portion of the formula, even though the end result 
> would fit in Last_GS
Using your way, (Max_Program_To_Display-1) is calculated first. Since
the variable is type word, it would make word calculation, with word
range. In such case, if Max_Program_To_Display is zero, you would get an
underflow (and with no bounds checks, you could get $ that would be
even worse).

>> Last_GS:=G_End-(longint(Max_Program_To_Display)-1);
> This aso fixes the warning if I leave all my variables alone.  If I 
> understand this correctly in this case longint() is a function that returns a 
> longint variable to be used in the calculation, so when it does the -1 it's 
> ok it that part of the formula ends up being negative.
>
> So now my question is, which is the best method to use?  My thinking with 
> declaring Max_Program_To_Display as a word was that this value has no meaning 
> if it is negative, and actually a word is way too generous for this value, a 
> byte would be overkill.

If negative has no sense, I would declare it word, or byte and cast it
to a signed integer if you need for internal calculations as have been
said. Declaring it word, you have made the compiler to give you heads-up
about a potential problem, then you can decide to check before if
Max_Program_To_Display is zero or double check there is nothing wrong
there. Other way it would have passed unnoticed and could bite you
latter in unexpected ways and points of execution, making you hunt for a
long time a weir bug.

I wouldn't worry too much about declaring it word or byte. I think that
because of performance, the compiler may align in a word (compiler gurus
will tell better).
In fact, I would forget about internal format and declare a new type in
the range of valid values i.e

type
 TMaxprogram=0..53;

and let the compiler decide what internal format to use.

In the conversion I would use "integer" instead of "longint"

Last_GS:=G_End-(integer(Max_Program_To_Display)-1);

"Integer" is the optimal integer format for that architecture, probably
"longint", but I would use "integer" anyway.

My two cents.

-- 
Saludos

Santiago A.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal