The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,854 other subscribers

Archive for the ‘Event’ Category

Smart Pointers code that compiles in FPC and Delphi

Posted by jpluimers on 2019/03/06

Delphi and FPC have different language boundaries, so it is always good to read a thread discussing how to get near-the-edge cases work in both.

This case is about Smart Pointers (here called auto pointers, maybe because auto_ptr is what they used to be called in C++): [WayBack] Hi all, I am trying to make a certain piece of code cross compile between Delphi and FPC. On FPC, it compiles fine but on Delphi I get a [dcc32 Error] P… – Ugochukwu Mmaduekwe – Google+

In the end if comes down to that Delphi does not allow forward-declaration of records (it does for interfaces and classes), but that you do not need a __PAutoPtr_T = ^__TAutoPtr_T, because you can use ^__TAutoPtr_T in parameters.

In Spring4D, they are called Shared/IShared/TShared, see my comment:

Note that since these are reference counted, you might want to call them shared_ptr. If you enforce the single-instance behaviour, observe that in C++ they are now called uniqe_ptr.

In Spring4D this rename has already taken place a while ago: https://bitbucket.org/sglienke/spring4d/commits/e252b81fd3788cf5b82588721f68d00c892deb87

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 2 Comments »

Application shutdown: wait for all threads to terminate or not?

Posted by jpluimers on 2019/02/21

A while ago, I ran into a problem that an anonymous thread would run longer than the main thread of the application.

This caused all sorts of trouble, so in this case I decided to fix it for that particular thread.

There are various opinions if this should be done for all threads or not. Like always, it depends, so it is good to mention a few:

This particular case resulted into the memory manager shutting down earlier than the anonymous thread, but the anonymous thread was still using memory allocation functions, resulting into a few things of which you do not want the first and second to happen on a continuous integration system:

  1. Error messages during shutdown, which is unwanted on a headless system:
    ---------------------------
    MyIntegrationTests.exe: MM Operation after uninstall.
    ---------------------------
    FastMM has detected a GetMem call after FastMM was uninstalled.
    ---------------------------
    OK 
    ---------------------------

    or

    ---------------------------
    MyIntegrationTests.exe: MM Operation after uninstall.
    ---------------------------
    FastMM has detected a FreeMem call after FastMM was uninstalled.
    ---------------------------
    OK 
    ---------------------------

    either of them followed by

    ---------------------------
    Error
    ---------------------------
    Runtime error 203 at 00408EFF
    ---------------------------
    OK 
    ---------------------------

    or

    ---------------------------
    Error
    ---------------------------
    Runtime error 204 at 0040AFE9
    ---------------------------
    OK 
    ---------------------------

    The errors are mappings of:

    203, { reOutOfMemory }
    204, { reInvalidPtr }
  2. The MyIntegrationTests_MemoryManager_EventLog.txt to rapidly grow to 100s of megabytes.
  3. The MyIntegrationTests_MemoryManager_EventLog.txt not to be truncated.

This particular case was easy to fix by adding a global (but implementation section contained) boolean indicating if the thread was already finished:

unit DebugInformationLoaderUnit;

interface

implementation

uses
  JclDebug;

var
  LoadDebugInformationAsyncFinished: Boolean = False;

procedure LoadDebugInformationAsync;
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.NameThreadForDebugging('LoadDebugInforoamtionAsync');
      DebugInfoAvailable(MainInstance);
      LoadDebugInformationAsyncFinished := True;
    end).Start;
end;

initialization
  LoadDebugInformationAsync;

finalization
  while not LoadDebugInformationAsyncFinished do
  begin
    Sleep(1);
  end;
end.

In addition, I did this to suppress message boxes outside Delphi:

program MyIntegrationTests;

...

{$Include FastMM4Options.inc}

uses
  FastMM4 in '..\..\..\Shared\FastMM4.pas',
  System.Classes,
...;

{$R *.RES}

begin
  TThread.NameThreadForDebugging(ParamStr(0));

  SuppressMessageBoxes := SuppressMessageBoxes // follow pattern in FastMM4.FinalizeMemoryManager
    {$ifdef RequireIDEPresenceForLeakReporting}
        and DelphiIsRunning
    {$endif}
    {$ifdef RequireDebuggerPresenceForLeakReporting}
        and ((DebugHook <> 0)
        {$ifdef PatchBCBTerminate}
        or (Assigned(pCppDebugHook) and (pCppDebugHook^ <> 0))
        {$endif PatchBCBTerminate}
        )
    {$endif}
    ;
  {$WARN SYMBOL_PLATFORM OFF} NoErrMsg := {$WARN SYMBOL_PLATFORM ON} SuppressMessageBoxes; // Set RTL message boxes as well;

  ...
end.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Passing the `–symbol-report` to the Delphi compiler gives you a nice XML overview with all symbols used

Posted by jpluimers on 2019/01/31

Cool undocumented parameter --symbol-report at the [WayBack/Archive] Hatena Diary mid 2017:

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, Undocumented Delphi | 7 Comments »

On my research list: Delphi; automatically generate class body from interface definition

Posted by jpluimers on 2019/01/23

Still need to research this: [WayBack] I search for way to automatically generate class body from interface definition… – Jacek Laskowski – Google+

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, ModelMaker Code Explorer, Software Development | 2 Comments »

Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized”…

Posted by jpluimers on 2019/01/21

Historically, [WayBack] W1036: Variable '%s' might not have been initialized (Delphi) has had a lot of gotchas.

The most important still is that it never show for managed types (strings, interfaces, etc).

Usually W1036 shows for non-managed types, but Dan Hacker has found a new case where it does not in [WayBack] Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized’ if the StringsToDo parameter in DoSomething is defined as a var… – Dan Hacker – Google+

He noticed it in Delphi XE and 10.2 Tokyo.

I tested it with the Win32 compiler in XE8.

This warns:

program W1036;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  System.Classes;

procedure DoSomething(var StringsToDo: TStringList); // <-------- this line makes the difference
begin
  //do nothing
end;

procedure Test;
var
  MyStrings : TStringList;
begin
  MyStrings.Free;   {W1036 warning if StringsToDo param is NOT var}
  DoSomething(MyStrings);
end;

begin
end.

This does not warn:

program W1036;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  System.Classes;

procedure DoSomething(StringsToDo: TStringList); // <-------- this line makes the difference
begin
  //do nothing
end;

procedure Test;
var
  MyStrings : TStringList;
begin
  MyStrings.Free;   {W1036 warning if StringsToDo param is NOT var}
  DoSomething(MyStrings);
end;

begin
end.

initially, I misread his report and reacted wrongly on the cause (but rightly on the suggested use case of var and of TStringList):

Because a var parameter means that the caller should pass in an initialised parameter. Otherwise it should be an out parameter, not a var parameter.

var parameter for reference types like TStrings (only pass as TStringList if it deliberately is not compatible with TStrings) is a risky thing anyway, because the called method can overwrite it and then the caller has to notice the change, then decide what to do with the previous value (likely free it).

I later correct myself:

Looking better, I think it is a compiler issue.

The only difference between nothing and var is the loading of the parameter as a pointer:

with var

//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8D45FC lea eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomething
without var
//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8B45FC mov eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomething

So:

  • with a var, a pointer to the instance of MyStrings (obtained by a lea instruction) gets pushed on the stack
  • without a var, the instance of MyStrings (obtained by a mov instruction) gets pushed on the stack.

For the difference metween mov and lea, and the use of [] brackets, see:

–jeroen

Source: Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been i…

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 3 Comments »

The biggest lie I tell myself is not about new years resolutions.

Posted by jpluimers on 2019/01/01

The biggest lie I tell myself is “I don’t need to write that down, I’ll remember it”

It’s likely older, but the oldest reference I could find was 2012 [WayBack].

So before I forget:

Happy New Year everyone!

With the above quote, it is no coincidence I started my blog even earlier (in 2009): it’s my off-line memory, way better readable than my hand-writing and indexed by various search engines.

Read the rest of this entry »

Posted in About, Conference Topics, Conferences, Event, LifeHacker, Personal, Power User | Leave a Comment »

Do not put IFDEF with relative paths in your .dpr as the Delphi IDE cannot match them in the .dproj

Posted by jpluimers on 2018/12/20

The Delphi IDE manages the .dpr and .dproj files for, trying to keep them in sync.

Some information is duplicated between the two, especially files referenced by relative paths: those files are contained in your project.

This means you cannot do something like this in your .dpr file:

  {$IFDEF DEBUG}
  Debug in '..\..\..\..\Shared\Debug.pas';
  {$ELSE}
  Debug in '..\Debug.pas'
  {$ENDIF}

There is no equivalent for this in the .dproj and it will confuse the IDE which file now actually is or is not inside your project.

Better to leave the file outside of your project, then modify the RELEASE/DEBUG search paths to have the correct one.

Even better is to have just one Debug.pas file containing the changes.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Never ever put OutpugDebugString in code that is meant to run on production systems

Posted by jpluimers on 2018/12/18

I just saw this code in the Delphi RTL enabled for RELEASE builds of the procedure TThreadPool.TQueueWorkerThread.Execute; code:

{$IFDEF MSWINDOWS}
    OutputDebugString(PChar(Format('Thread Exiting: %d', [ThreadId])));
{$ENDIF}

Never, ever do this.

If you code review code that contains it: ensure it has some kind of compile time DEBUG conditional around it.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 12 Comments »

Delphi 10.3 Rio got released; I’ll wait a while hoping to see more positive comments

Posted by jpluimers on 2018/11/22

The first messages on G+ saw about Delphi 10.3 Rio are these:

Related:

I think I will wait a while before installing until more positive messages are being published.

If you do want to try, the hashes of delphicbuilder10_3_0_94364.iso are these:

crc32  157b6e36
md5    0882d58cb53a7d0a828cc45d06c6ecd0
sha1   21579b530f781895885923809d9e670b439ebf9d
sha256 9213de93c2abdd6a2ee23aa84fc7e63a87d62d0344f0d0f0ee162d0e7dce7c7d

and for the radstudio10_3_0_esd_94364.exe they are:

crc32  033aeb53
md5    b25fab9d5f0724fb1d59ea77deff6702
sha1   289bbf33c90ae43b151af116e1e7c7a5348591e6
sha256 fb9a825ddaf235441ff72c10fbb03d2cf94adb3f037508e69f0978a37dc95773

jeroen  

PS: [WayBack] How to verify file hashes on macOS | ModMy

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Solution for Delphi – post-build event with multiple if/copy combinations only execute if first file does not exist – Stack Overflow

Posted by jpluimers on 2018/11/15

My solution in [WayBack] delphi – post-build event with multiple if/copy combinations only execute if first file does not exist – Stack Overflow is an addendum to my 2014 post Delphi prebuild/prelink/postbuild events.

Here we go:

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, The Old New Thing, Windows Development | Leave a Comment »