Posts

Hello Old New Leaky Friend

Image
Developers that extensively use interfaces in Delphi probably know about a long-standing issue with the compiler, where interface parameters declared as const or [ref] will cause a memory leak if a reference-counted object instance is constructed directly at the call site. Illustration: Sandra Prasnikar        Specifically, the following code would create a leak: procedure LeakTest(const Intf: IInterface); begin end; procedure Run; begin LeakTest(TInterfacedObject.Create); end; begin ReportMemoryLeaksOnShutdown := True; Run; end. The problem arises because the compiler does not create a hidden interface reference that would properly initialize the reference counting mechanism and keep the object instance alive during the call. In other words, such an object would never be assigned to a strong interface reference. Because const and [ref] parameters don't trigger reference counting, if there is no other code within the called routine, the obj...

Delphi 12.1 & New Quality Portal Released

Image
The Delphi 12.1 update has been released. Besides a number of bug fixes, this release also has a few new features. The most notable ones are the new Split Editor, which allows having multiple files opened side by side; and support for Android API 34. You can find more information about what is new in this update at https://docwiki.embarcadero.com/RADStudio/Athens/en/12_Athens_-_Release_1 However, the greatest change for all Delphi developers is a new bug tracking portal that replaces the old one, still available in read-only mode at https://quality.embarcadero.com/ . The new portal is hosted in Atlassian Cloud https://embt.atlassian.net/servicedesk/customer/portals  or through a redirect https://qp.embarcadero.com and is based on Jira Service Management (JSM), while the internal bug tracking system, which was also migrated to the cloud, was not changed and is running on Jira. This move to the cloud was inevitable, because Atlassian retired their Server line of products. JSM i...

Catch Me If You Can - Part II

It has been quite some time since I wrote the Catch Me If You Can post about the inability of LLVM-backed compilers to catch non-call hardware exceptions. In other words, hardware exceptions raised by code written in the same block as the try...except exception handler. Since then, more LLVM-backed compilers have been added to Delphi, and with those, more reasons to change common coding practices... but still, very few developers know about the issue. The original article covered only try...except exception handlers, and exploring what exactly happens with implicit and explicit try...finally handlers was left as an exercise to the readers and to some future, now long overdue, post. And Now: All Hell Breaks Loose When you read about non-call hardware exceptions not being caught by an immediate try...except block, the implications might not look too serious. After all, while plenty of code can raise exceptions, try...except handlers are not that frequently used in places, as mo...

Coming in Delphi 12: Disabled Floating-Point Exceptions

Delphi 12 is in the works. One of its small features that will have a huge impact is a change in the default handling of floating-point exceptions, which will now be masked on all platforms. Previously, floating-point exception handling was different across platforms, and most notably on the Windows platform: In VCL and console applications, floating-point exceptions were not masked and would raise an exception. On the other hand, FireMonkey applications had all floating-exceptions masked by default, regardless of which platform they were running on. Basically if you haven't explicitly changed the exception mask in your code to some value other than the default, and you had code that attempted to divide some number with zero, you would get an EZeroDivide exception in previous Delphi versions on the Windows VCL application. In Delphi 12, there is no exception, and the result of such a division will be +INF . So the following code will no longer raise an exception. If you were r...

Beware of loops and tasks

Loops and anonymous methods don't go hand in hand. Any variable that changes for each iteration will cause problems if it is used within an anonymous method. I explained the mechanism behind variable capturing in the post Mysterious Case Of Wrong Value , along with the problem it causes with loops and its solution. Commonly, anonymous methods are used as callbacks or event handlers, where there are no loops in the context where variable capture happens. While there is a possibility to have an unexpected—wrong—value in such scenarios, it is rather easy to debug them and understand the order in which some code is called, and why the captured value is wrong in a given place. With the rise of multi-threading usage, and especially the Parallel Programming Library and tasks, writing anonymous methods inside a loop becomes more common, and it is much easier to write code where a captured variable will have the wrong value. The biggest problem with such code is that it will be harder to ...

Assigning result to a function from asynchronous code

One of the more common problems that comes up in multi-threading, especially when refactoring existing code, is assigning a result obtained from asynchronous code. In other words, how do you write a function that will return some value, and calculate that value in a background thread? Basically, converting the following code: function GetData(...): string; var Data: string; begin Data := LongTask(...); // assign result of a long-running task to a function Result := Data; end; To this one: function GetData(...): string; var Data: string; begin TThread.CreateAnonymousThread( procedure begin Data := LongTask(...); end).Start; // assign result of a long-running task to a function Result := Data; end; Now, the above code will compile, but it will not achieve the desired functionality. Even if we ignore its thread safety issues (the background thread writes to the Data variable and that can interfere with assigning it to the function result), the funct...

DelphiCon 2023: NX Horizon - The Open Source Event Bus for Delphi Replay

Image
 Did you miss the DelphiCon session on "NX Horizon - The Open Source Event Bus for Delphi"?  The webinar replay is now available!  Code can be found on GitHub: https://github.com/dalijap/nx-horizon Replay can be found at:  https://www.youtube.com/watch?v=axu53AatjHc