Delphi Memory Issue (FastMM4) - delphi

Working on a project which uses factories to construct objects. I keep the pointers to the factory functions in vars globally (bad I know) and register them on initialization.
I recently was interested in seeing if the project had memory leaks so decided to download FastMM4 and have a look through. It came up with a few errors that I could fix but this one I'm a bit stumped on seems by me not freeing the memory related to the factory as shown in the code below I'm getting a small memory leak. Not ridiculous but annoying nevertheless.
What would I use to free the memory (if it is that) i've tried dispose(#factoryfunction) but seems to mangle everything. I'm not too good with low level pointer stuff always confuses the hell out of me so if someone could help that would be great.
I've included an example below that i've just written off the top of my head that illustrates the problem I'm having.
Cheers,
Barry
unit Test;
interface
uses classes;
type
TAFactoryFunction = reference to function (const aType : integer): TObject;
function testfunction (const aType : integer) : TObject;
implementation
function testfunction(const aType: integer) : TObject;
begin
result := TObject.Create;
end;
var
FactoryFunction : TAFactoryFunction
initialization
FactoryFunction := testfunction;
finalization
// possibly some freemem code here?
end.

I just tested this in Delphi 2010 and it appears to be a bug. The compiler should generate code to clean that up, but it isn't. Even writing FactoryFunction := nil, as David suggested, doesn't work.
You should report this in QC as an error.

Related

Why does FreeAndNil sets nil before freeing the object? [duplicate]

If you will look at the code of FreeAndNil procedure you will see:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
What is the reason they assigning Nil to an object reference and only after this destroying it? Why not vice-versa?
I can think of two reasons for doing it this way round, neither of which seems at all compelling.
Reason 1: to guarantee that the reference is set to nil in case an exception is raised
The implementation achieves this. If the destructor raises, then the reference is still set to nil. Another way to do so would be with a finally block:
try
TObject(Obj).Free;
finally
TObject(Obj) := nil;
end;
The downside of this is performance. Particularly on x86 a try/finally is a little expensive. In such a fundamental routine it is prudent to avoid this expense.
Why do I find the desire to nil at all costs not to be compelling? Well, as soon as destructor start failing you may as well give up. You can no longer reason clearly about your program's state. You cannot tell what failed and what state your program is in. It is my view that the correct course of action in the face of a destructor that raises is to terminate the process.
Reason 2: to ensure that other threads can detect that the object is being destroyed
Again this is achieved but it is of no practical use. Yes you can test whether the reference is assigned or not. But then what? The other thread cannot call methods on the object without synchronization. All you could do is learn whether or not the object is alive. And if that is so, why would it matter if this status changed before or after the destructor runs?
So whilst I present this as a possible reason I cannot believe that anyone in Embarcadero was really swayed by this argument.
There's a variation on David's second reason that is a little more compelling. Although one might argue that if it applies there are other problems that should be fixed.
Reason 3: to ensure event handlers on the same thread can detect that the object is being destroyed
Here's a concocted hypothetical example:
TOwner.HandleCallback;
begin
if Assigned(FChild) then
FChild.DoSomething;
end;
TChildClass.Destroy;
begin
if Assigned(FOnCallback) then FOnCallback;
inherited Destroy;
end;
Now if TOwner calls:
FChild.Free;
FChild := nil;
FChild will be asked to DoSomething in the middle of its destruction cycle. A certain recipe for disaster. The implementation of FreeAndNil neatly avoids this.
Yes you may argue that firing callback events during destruction is dangerous, but it does have its benefits. There are quite few examples in Delphi/VCL code. Especially if you expand the scope of concern to include calling polymorphic methods - which also put aspects of the destruction sequence outside of your control.
Now I must point out that I'm not aware of any specifc cases in Delphi library code where this problem could manifest. But there are some complex circular dependencies in parts of the VCL. So I wouldn't be surprised if changing the implementation to the more obvious choice in SysUtils leads to a few unpleasant surprises.
The only thing that really bothered me for years is that FreeAndNil(var obj) lacks type safety. I know that due to the lack of adequate language support there was simply no way to do it right, but since we have generics for a while, here's a quick and simple tool that can make your life easier.
type
TypeSafe = class sealed
public
class procedure FreeAndNil<T : class>( var obj : T); static; inline;
end;
class procedure TypeSafe.FreeAndNil<T>( var obj : T);
begin
SysUtils.FreeAndNil( obj);
end;
If you add an overload for the normal FreeAndNil(var Obj) and mark it as deprecatedyou got a fair chance to find all the places where someone hands over an interface pointer to it -- and if the code base is only large enough you will find interesting things, believe me.
procedure FreeAndNil(var Obj); inline; deprecated 'use TypeSafe.FreeAndNil<T>() instead';
Note that you don't even have to specify the <T>since the compiler is smart enough to find out the right type for you. Just add the unit on top and change all
FreeAndNil(foobar);
in your source code into
TypeSafe.FreeAndNil(foobar);
and you're done.

Store array in TQueue possible?

Having problem storing an array in a TQueue. Any idea where I go wrong?
Code works fine in Delphi XE 5 but not in Delphi 10 Seattle.
(I can't decide if this is a bug or how it should work. Tried searching embarcadero for clues but failed.)
procedure TForm1.Button1Click(Sender: TObject);
var
FData: TQueue<TBytes>;
FsData: TQueue<String>;
arr: TBytes;
begin
FData := TQueue<TBytes>.Create;
FsData := TQueue<String>.Create;
try
setlength(arr, 3);
arr[0] := 1;
arr[1] := 2;
arr[2] := 3;
FData.Enqueue(arr);
Memo1.Lines.Add('Count, array:' + IntToStr(FData.Count)); // 0?
FsData.Enqueue('asada');
Memo1.Lines.Add('Count, string:' + IntToStr(FsData.Count)); // 1
finally
FData.Free;
FsData.Free;
end;
end;
This is a defect introduced in XE8. Here's the simplest reproduction that I can produce.
{$APPTYPE CONSOLE}
uses
System.Generics.Collections;
var
Queue: TQueue<TArray<Byte>>;
begin
Queue := TQueue<TArray<Byte>>.Create;
Queue.Enqueue(nil);
Writeln(Queue.Count);
end.
The output is 1 in XE7 and 0 in XE8 and Seattle.
This has already been reported to Embarcadero: RSP-13196.
The implementation of Enqueue looks like this:
procedure TQueue<T>.Enqueue(const Value: T);
begin
if IsManagedType(T) then
if (SizeOf(T) = SizeOf(Pointer)) and (GetTypeKind(T) <> tkRecord) then
FQueueHelper.InternalEnqueueMRef(Value, GetTypeKind(T))
else
FQueueHelper.InternalEnqueueManaged(Value)
else
case SizeOf(T) of
1: FQueueHelper.InternalEnqueue1(Value);
2: FQueueHelper.InternalEnqueue2(Value);
4: FQueueHelper.InternalEnqueue4(Value);
8: FQueueHelper.InternalEnqueue8(Value);
else
FQueueHelper.InternalEnqueueN(Value);
end;
end;
When T is a dynamic array, the FQueueHelper.InternalEnqueueMRef branch is chosen. This in turn looks like this:
procedure TQueueHelper.InternalEnqueueMRef(const Value; Kind: TTypeKind);
begin
case Kind of
TTypeKind.tkUString: InternalEnqueueString(Value);
TTypeKind.tkInterface: InternalEnqueueInterface(Value);
{$IF not Defined(NEXTGEN)}
TTypeKind.tkLString: InternalEnqueueAnsiString(Value);
TTypeKind.tkWString: InternalEnqueueWideString(Value);
{$ENDIF}
{$IF Defined(AUTOREFCOUNT)}
TTypeKind.tkClass: InternalEnqueueObject(Value);
{$ENDIF}
end;
end;
Note that there is no entry for TTypeKind.tkDynArray. Because these two methods are inlined, the inliner manages to compress it all down to nothing. No action is performed when you Enqueue a dynamic array.
Back in the good old days of XE7 the code looked like this:
procedure TQueue<T>.Enqueue(const Value: T);
begin
if Count = Length(FItems) then
Grow;
FItems[FHead] := Value;
FHead := (FHead + 1) mod Length(FItems);
Inc(FCount);
Notify(Value, cnAdded);
end;
No scope for type specific defects there.
I don't think that there's an easy workaround for you. Perhaps the most expedient way to proceed is to take the code for the XE7 TQueue and use that in place of the broken implementation from XE8 and Seattle. For the record, I've given up on the Embarcadero generic collections and use my own classes.
The back story here is that in XE8, Embarcadero decided to address a deficiency in their implementation of generics. Whenever you instantiate a generic type, copies of all the methods are created. For some methods, identical code is generated for different instantiations.
So it is quite common for TGeneric<TFoo>.DoSomething and TGeneric<TBar>.DoSomething to have identical code. Other compilers for other languages, C++ templates, .net generics, etc., recognise this duplication and merge together identical generic methods. The Delphi compiler does not. The end result is a larger executable than strictly necessary.
In XE8 Embarcadero decided to tackle this in what I regard was utterly the wrong way. Instead of attacking the root cause of the issue, the compiler, they decided to change the implementation of their generic collection classes. If you look at the code in Generics.Collections, you will see that it has been completely re-written in XE8. Where previously the code from XE7 and earlier was readable, from XE8 it is now exceedingly complex and opaque. This decision had the following consequences:
The complex code contained many errors. Many of these were found shortly after XE8 was released and have been fixed. You have stumbled upon another defect. One thing that we have learnt is that Embarcadero's internal test suite does not exercise their collection classes sufficiently. It is manifestly clear that their tests are inadequate.
By changing their library rather than the compiler, they have patched up the RTL classes. The original issue with generic code bloat remains for third party classes. Had Embarcadero fixed the issue at source then not only could they have retained the simple and correct collection class code from XE7, but all third generic code would have benefited.

Why FreeAndNil implementation doing Nil before Free?

If you will look at the code of FreeAndNil procedure you will see:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
What is the reason they assigning Nil to an object reference and only after this destroying it? Why not vice-versa?
I can think of two reasons for doing it this way round, neither of which seems at all compelling.
Reason 1: to guarantee that the reference is set to nil in case an exception is raised
The implementation achieves this. If the destructor raises, then the reference is still set to nil. Another way to do so would be with a finally block:
try
TObject(Obj).Free;
finally
TObject(Obj) := nil;
end;
The downside of this is performance. Particularly on x86 a try/finally is a little expensive. In such a fundamental routine it is prudent to avoid this expense.
Why do I find the desire to nil at all costs not to be compelling? Well, as soon as destructor start failing you may as well give up. You can no longer reason clearly about your program's state. You cannot tell what failed and what state your program is in. It is my view that the correct course of action in the face of a destructor that raises is to terminate the process.
Reason 2: to ensure that other threads can detect that the object is being destroyed
Again this is achieved but it is of no practical use. Yes you can test whether the reference is assigned or not. But then what? The other thread cannot call methods on the object without synchronization. All you could do is learn whether or not the object is alive. And if that is so, why would it matter if this status changed before or after the destructor runs?
So whilst I present this as a possible reason I cannot believe that anyone in Embarcadero was really swayed by this argument.
There's a variation on David's second reason that is a little more compelling. Although one might argue that if it applies there are other problems that should be fixed.
Reason 3: to ensure event handlers on the same thread can detect that the object is being destroyed
Here's a concocted hypothetical example:
TOwner.HandleCallback;
begin
if Assigned(FChild) then
FChild.DoSomething;
end;
TChildClass.Destroy;
begin
if Assigned(FOnCallback) then FOnCallback;
inherited Destroy;
end;
Now if TOwner calls:
FChild.Free;
FChild := nil;
FChild will be asked to DoSomething in the middle of its destruction cycle. A certain recipe for disaster. The implementation of FreeAndNil neatly avoids this.
Yes you may argue that firing callback events during destruction is dangerous, but it does have its benefits. There are quite few examples in Delphi/VCL code. Especially if you expand the scope of concern to include calling polymorphic methods - which also put aspects of the destruction sequence outside of your control.
Now I must point out that I'm not aware of any specifc cases in Delphi library code where this problem could manifest. But there are some complex circular dependencies in parts of the VCL. So I wouldn't be surprised if changing the implementation to the more obvious choice in SysUtils leads to a few unpleasant surprises.
The only thing that really bothered me for years is that FreeAndNil(var obj) lacks type safety. I know that due to the lack of adequate language support there was simply no way to do it right, but since we have generics for a while, here's a quick and simple tool that can make your life easier.
type
TypeSafe = class sealed
public
class procedure FreeAndNil<T : class>( var obj : T); static; inline;
end;
class procedure TypeSafe.FreeAndNil<T>( var obj : T);
begin
SysUtils.FreeAndNil( obj);
end;
If you add an overload for the normal FreeAndNil(var Obj) and mark it as deprecatedyou got a fair chance to find all the places where someone hands over an interface pointer to it -- and if the code base is only large enough you will find interesting things, believe me.
procedure FreeAndNil(var Obj); inline; deprecated 'use TypeSafe.FreeAndNil<T>() instead';
Note that you don't even have to specify the <T>since the compiler is smart enough to find out the right type for you. Just add the unit on top and change all
FreeAndNil(foobar);
in your source code into
TypeSafe.FreeAndNil(foobar);
and you're done.

Wrong code when combining anonymous and nested procedures

I've got some unexpected access violations for Delphi code that I think is correct, but seems to be miscompiled. I can reduce it to
procedure Run(Proc: TProc);
begin
Proc;
end;
procedure Test;
begin
Run(
procedure
var
S: PChar;
procedure Nested;
begin
Run(
procedure
begin
end);
S := 'Hello, world!';
end;
begin
Run(
procedure
begin
S := 'Hello';
end);
Nested;
ShowMessage(S);
end);
end;
What happens for me is that S := 'Hello, world!' is storing in the wrong location. Because of that, either an access violation is raised, or ShowMessage(S) shows "Hello" (and sometimes, an access violation is raised when freeing the objects used to implement anonymous procedures).
I'm using Delphi XE, all updates installed.
How can I know where this is going to cause problems? I know how to rewrite my code to avoid anonymous procedures, but I have trouble figuring out in precisely which situations they lead to wrong code, so I don't know where to avoid them.
It would be interesting to me to know if this is fixed in later versions of Delphi, but nothing more than interesting, upgrading is not an option at this point.
On QC, the most recent report I can find the similar #91876, but that is resolved in Delphi XE.
Update:
Based on AlexSC's comments, with a slight modification:
...
procedure Nested;
begin
Run(
procedure
begin
S := S;
end);
S := 'Hello, world!';
end;
...
does work.
The generated machine code for
S := 'Hello, world!';
in the failing program is
ScratchForm.pas.44: S := 'Hello, world!';
004BD971 B89CD94B00 mov eax,$004bd99c
004BD976 894524 mov [ebp+$24],eax
whereas the correct version is
ScratchForm.pas.45: S := 'Hello, world!';
004BD981 B8B0D94B00 mov eax,$004bd9b0
004BD986 8B5508 mov edx,[ebp+$08]
004BD989 8B52FC mov edx,[edx-$04]
004BD98C 89420C mov [edx+$0c],eax
The generated code in the failing program is not seeing that S has been moved to a compiler-generated class, [ebp+$24] is how outer local variables of nested methods are accessed how local variables are accessed.
Without seeing the whole Assembler Code for the whole (procedure Test) and only assuming on the Snippet you posted, it's probably that on the failing Snippet only a Pointer has been moved where on the correct version there is some Data moved too.
So it seems that S:=S or S:='' causes the Compiler to create a reference by it's own and could even allocate some Memory, which would explain why it works then.
I also assume that's why a Access Violation occurs without S:=S or S:='', because if there is no Memory allocated for the String (remember you only declared S: PChar) then a Access Violation is raised because non-allocated Memory was accessed.
If you simply declare S: String instead, this probably won't happen.
Additions after extended Commenting:
A PChar is only a Pointer to Data Structure, that must exist. Also another common Issue with PChar is to declare local Variables and then passing a PChar to that Variable to other Procs, because what happens is that the local Variable is freed once the routine ends, but the PChar will still point to it, which then raise Access Violations once accessed.
The only possibility that exists per Documentation is declaring something like that const S: PChar = 'Hello, world!' this works because the Compiler can resolve a relative Adresse to it. But this only works for Constants and not for Variables like on the Example above. Doing it like in the Example above needs Storage to be allocated for the string literal to which the PChar then points to like S:String; P:PChar; S:='Hello, world!'; P:=PChar(S); or similar.
If it still fails with declaring String or Integer then perhaps the Variable disappears somewhere along or suddenly isn't visible anymore in a proc, but that would be another Issue that has nothing to do with the existing PChar Issue explained already.
Final Conclusion:
It's possible to do S:PChar; S:='Hello, world!' but the Compiler then simply allocates it as a local or global Constant like const S: PChar = 'Hello, world!' does which is saved into Executable, a second S := 'Hello' then creates another one which is also saved into Executable and so on - but S then only points to the last one allocated, all others are still in the Executable but not accessible any more without knowing the exact Location, because S only points to the last one allocated.
So depending which one was the last S points either to Hello, world! or Hello. On the Example above i can only guess which one was the last and who knows perhaps the Compiler can only guess too and depending on optimizations and other unpredictable Factors S could suddenly point to unallocated Mem instead of the last one by the Time Showmessage(S) is executed which then raises a Access Violation.
How can I know where this is going to cause problems?
It's hard to tell at this point in time.
If we knew the nature of the fix in Delphi XE2 we'd be in a better position.
All you can do is refrain from using anonymous functions.
Delphi has had procedural variables, so the need for anonymous functions ready is not that dire.
See http://www.deltics.co.nz/blog/posts/48.
It would be interesting to me to know if this is fixed in later versions of Delphi
According to #Sertac Akyuz this has been fixed in XE2.
Personally I dislike anonymous methods and have had to ban people from using them in my Java projects because a sizable proportion of our code base was going anonymous (event handlers).
Used in extreme moderation I can see the use case.
But in Delphi where we have procedural variables and nested procedures... Not so much.

Delphi: F2084 Internal Error T2575

Do anybody know what this error means?
It comes and goes in one of my units. Adding a space or a lineshift will sometime solve it, sometime not...
I'm using Delphi 2007.
Here is a Delphi internal error guide that will perhaps help you. Internal error often can be resolved by deleting DCU files, restarting the IDE or not using a tool that speeds up Delphi start (like DelphiSpeedUp).
But in most cases, this is some weird bug in the Delphi compiler and if you know to work around it and this won't be to costy, do this and be happy. I once had the console version dcc32 crashing (IDE compiled fine) when I increased a variable with Inc and using addition instead of Inc solved the problem...
Best thing to do is report this to CodeGear. It really helps if you can find a way to consistently cause the bug on purpose, so they can track it down more easily.
One simple way to get an internal error is to use cut&paste to create a new routine. I moved all code within an IF block to a new procedure and got internal error T2335 at the End of the new proc (in Delphi 7).
The error was caused by the line "If (Something) then Break;". The problem was, this code was no longer within a loop, so there was nothing to break from. Changing 'Break' to 'Exit' fixed the problem.
So look for Break and Continue statements.
All internal errors are things that shouldn't have happened, but did. Check QC and if it isn't there report it. If you can provide a way to reproduce it that will make it more likely they can fix it.
Usually for internal erros I do a full build or restart Delphi.
I've had this problem too, and i've tested many solutions, but non of them helped me.
then i've found this cause of error:
in error occurring function, i had an Inc() func that was trying to inc a String Variable!!
so i've fixed that bug and everything turned to normal :)
I had another case today (D2010), everything perfectly legal syntax since good ol' Turbo Pascal days:
type
TValueRec = record
selector : (int,str,unk);
intVal : Integer;
strVal : WideString;
unkVal : IUnknown;
end;
Using this record in a method of a generics-based class brought me an "F2084 internal error: AV0661CFEF-R0000000C-0" somewhere in the middle of another unit.
Changing it this way did the trick for me:
type
TValueRecSelector = (int,str,unk);
TValueRec = record
selector : TValueRecSelector;
intVal : Integer;
strVal : WideString;
unkVal : IUnknown;
end;
However, very annoying that such things produce such errors at completely unrelated places in the code.
I got this error in one instance:
procedure TDMData.SetValue(AValue: Word);
var
prevValue: Word;
method: TMethod;
begin
if FValue = AValue then
Exit;
prevValue := FValue;
FValue := AValue;
for method in FValueChangeEvent.Notifications do
TDMDataValueChangeNotification(method)(Self, AValue, prevValue);
end; // <--- Fatal: F2084 Internal Error: T2575
Both the GetNotifications Notifications property and the GetEnumerator method of the record returned by GetNotifications had an inline directive. Only by removing the inline from GetEnumerator the problem went away.
Note: similar functions were not causing this internal error!

Resources