Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-03

Class constructor called unconditionally

16 messages · 7 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

silvioprog

Hello,

First, take a look at this small project:

=== code ===

program Project1;
{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$IFDEF MSWINDOWS}
  {$APPTYPE CONSOLE}
{$ENDIF}
type
  TFoo = class
  public
    class constructor Create;
  end;
  class constructor TFoo.Create;
  begin
    Writeln('TFoo.Create called');
  end;
begin
  Writeln('Program start');
  Readln;
end.

=== /code ===

When you compile and run it in FPC, the result is:

=== result ===

TFoo.Create called
Program start

=== /result ===

But, if you compile and run this same code in Delphi (I'm using Seattle), the result is:

=== result ===

Program start

=== /result ===

Googling about this problem, I found this link at StackOverflow:

http://stackoverflow.com/questions/6231871/class-constructor-not-called-when-class-registration-is-done-in-that-class-const

With this comment:

"Uwe Raabe answered Jun 3 '11 at 19:55: As long as you don't use the class anywhere outside the class itself, the compiler takes this as the class not used at all and hence won't call the class constructor. So I guess you have to use the intialization section instead of tweaking the code to fool the compiler. Take the pragmatic approach instead of the dogmatic one. It will be more readable anyway."

After read this explanations, is there some compiler option to make FPC with this same Delphi behaviour? I'm using MODE DELPHI.

Thank you!

Silvio Clécio
Sven Barth
to silvioprog
"silvioprog" wrote
After read this explanations, is there some compiler option to make FPC

with this same Delphi behaviour? I'm using MODE DELPHI.

No, there is not. Currently class constructors (and destructors) are called always.

Regards,
Sven

silvioprog
to Sven Barth
Sven Barth wrote 10 lines
Am 31.03.2016 15:33 schrieb "silvioprog" : > After read this explanations, is there some compiler option to make FPC with this same Delphi behaviour? I'm using MODE DELPHI. No, there is not. Currently class constructors (and destructors) are called always. Regards, Sven

OK. So I can't use class constructor in FPC.

Thank you!

Silvio Clécio
Vojtěch Čihák
to silvioprog: First, take a look at this small project: === code === program Project1; {$IFDEF FPC}…

IMO compilers should be dogmatic otherwise one cannot rely on them. This looks to me like advocating wrong optimization.  
Blaazen
______________________________________________________________

Show quoted text 5 lines
Od: silvioprog Komu: "FPC-Pascal users discussions" Datum: 31.03.2016 15:33 Předmět: [fpc-pascal] Class constructor called unconditionally

 As long as you don't use the class anywhere outside the class itself, the compiler takes this as the class not used at all and hence won't call the class constructor. So I guess you have to use the intialization section instead of tweaking the code to fool the compiler. Take the pragmatic approach instead of the dogmatic one. It will be more readable anyway.-- Silvio Clécio

----------

silvioprog
to Vojtěch Čihák
Vojtěch Čihák wrote 7 lines
IMO compilers should be dogmatic otherwise one cannot rely on them. This looks to me like advocating wrong optimization. Blaazen

Thanks for reply Vojtěch, but are you referring to Delphi or FPC optimization?

I think that FPC should keep the Delphi class constructor behaviour in MODE DELPHI, allowing the programmers to port Delphi libraries to FPC, but ...

Silvio Clécio
Michael Van Canneyt
to silvioprog
silvioprog wrote 13 lines
On Thu, Mar 31, 2016 at 10:58 AM, Vojtěch Čihák wrote: > IMO compilers should be dogmatic otherwise one cannot rely on them. This > looks to me like advocating wrong optimization. > > > > Blaazen > Thanks for reply Vojtěch, but are you referring to Delphi or FPC optimization?

In general. You should never rely on such behaviour. This is not very robust programming.

I think that FPC should keep the Delphi class constructor behaviour in MODE DELPHI, allowing the programmers to port Delphi libraries to FPC, but ...

I suspect the problem is not in the mode, but in detecting whether a class is used or not in a program. It becomes very complicated when you use e.g. run-time packages.

Delphi itself is buggy in this regard, and has been since at least D7. For this reason, in general I advise against extensive use of initialization sections etc...

Michael.

silvioprog
to Michael Van Canneyt

On Thu, Mar 31, 2016 at 11:28 AM, Michael Van Canneyt <

wrote:

[...]

Show quoted text 5 lines
I suspect the problem is not in the mode, but in detecting whether a class is used or not in a program. It becomes very complicated when you use e.g. run-time packages.

Hm... so FPC class constructor (or class initialization) works like unit initialization.

Delphi itself is buggy in this regard, and has been since at least D7. For this reason, in general I advise against extensive use of initialization sections etc...

Thanks for sharing this information.

It's hard to make test-case when the code has an extensive use of initialization sections, so currently I'm avoiding it too. However, I need to register some classes in a class list, so I'm changing my code to do it in some place like application initialization.

Silvio Clécio
Michael Van Canneyt
to silvioprog
silvioprog wrote 12 lines
On Thu, Mar 31, 2016 at 11:28 AM, Michael Van Canneyt < > wrote: [...] > I suspect the problem is not in the mode, but in detecting whether a class > is used > or not in a program. It becomes very complicated when you use e.g. > run-time packages. > Hm... so FPC class constructor (or class initialization) works like unit initialization.

I imagine so, yes.

It is one of the reasons why I don't really see the usefulness of this construct, except that it looks OOP-ish.

I am guessing it comes from C++/Java/C#, which AFAIK do not have the 'initialization' section. But that's just a guess.

Show quoted text 13 lines
> Delphi itself is buggy in this regard, and has been since at least D7. > For this reason, in general I advise against extensive use of > initialization sections etc... Thanks for sharing this information. It's hard to make test-case when the code has an extensive use of initialization sections, so currently I'm avoiding it too. However, I need to register some classes in a class list, so I'm changing my code to do it in some place like application initialization.

I usually have a 'Start Application' kind of routine where I register all the necessary things, link things together (needed if you follow 'loosely coupled' design).

Michael.

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
I am guessing it comes from C++/Java/C#, which AFAIK do not have the 'initialization' section. But that's just a guess.

[my personal opinion - feel free to ignore this paragraph]

I hate such "features" pulled in from other languages, when Object Pascal already had perfectly good solutions (Object vs Record with Methods is another example). It really feels like it is polluting the Object Pascal language.

I usually have a 'Start Application' kind of routine where I register all the necessary things, link things together (needed if you follow 'loosely coupled' design).

I do the same. The tiOPF project follows a similar path in the core framework and its UnitTest suite. It works well.

Regards,
- Graeme -

Vojtěch Čihák
to silvioprog: On Thu, Mar 31, 2016 at 10:58 AM, Vojtěch Čihák Thanks for reply Vojtěch, but are you…

I meant Delphi optimization but I'm mistaking since they have it documented.  
B.
______________________________________________________________

Show quoted text 5 lines
Od: silvioprog Komu: "FPC-Pascal users discussions" Datum: 31.03.2016 16:17 Předmět: Re: [fpc-pascal] Class constructor called unconditionally

On Thu, Mar 31, 2016 at 10:58 AM, Vojtěch Čihák < > wrote: IMO compilers should be dogmatic otherwise one cannot rely on them. This looks to me like advocating wrong optimization.  
Blaazen
Thanks for reply Vojtěch, but are you referring to Delphi or FPC optimization?I think that FPC should keep the Delphi class constructor behaviour in MODE DELPHI, allowing the programmers to port Delphi libraries to FPC, but ...-- Silvio Clécio

----------

Dmitry Boyarintsev
to Graeme Geldenhuys: [my personal opinion - feel free to ignore this paragraph] I hate such "features" pulled…

On Thu, Mar 31, 2016 at 11:28 AM, Graeme Geldenhuys <

Show quoted text 10 lines
wrote: On 2016-03-31 16:06, Michael Van Canneyt wrote: > I usually have a 'Start Application' kind of routine where I register all > the necessary things, link things together (needed if you follow 'loosely > coupled' design). I do the same. The tiOPF project follows a similar path in the core framework and its UnitTest suite. It works well.

One could use an alternative approach and have "binding" units. The unit would consist of initialization section only, that does the necessary binding code.

They allow to avoid code within "start application" routine across different projects.
At the same time they keep the actual library units free of initialization.

thanks,
Dmitry

Maciej Izak
to Michael Van Canneyt: I imagine so, yes. It is one of the reasons why I don't really see the usefulness of this…

2016-03-31 17:06 GMT+02:00 Michael Van Canneyt :

Show quoted text 6 lines
I imagine so, yes. It is one of the reasons why I don't really see the usefulness of this construct, except that it looks OOP-ish.

It is mostly for initialization "class var" related stuff inside records and classes. Very usefully especially with generics.

Even more - there is no workaround for class constructor/destructor when generics are used (more details in Generics.Collections for example for "cuckoo" dictionary).

Current implementation is DEFINITELY buggy and mentioned in topic behavior should be reported as bug. Class constructor/destructor should be used only when type is somehow used in code or when is used directive like {$STRONGLINKTYPES ON} (which FPC don't have).

another bugs related to class constructor/destructor: http://bugs.freepascal.org/view.php?id=28911
http://bugs.freepascal.org/view.php?id=29245

Best regards, Maciej Izak
Michael Van Canneyt
to Dmitry Boyarintsev: On Thu, Mar 31, 2016 at 11:28 AM, Graeme Geldenhuys < One could use an alternative…
Dmitry Boyarintsev wrote 19 lines
On Thu, Mar 31, 2016 at 11:28 AM, Graeme Geldenhuys < > wrote: > On 2016-03-31 16:06, Michael Van Canneyt wrote: >> I usually have a 'Start Application' kind of routine where I register all >> the necessary things, link things together (needed if you follow 'loosely >> coupled' design). > > I do the same. The tiOPF project follows a similar path in the core > framework and its UnitTest suite. It works well. > One could use an alternative approach and have "binding" units. The unit would consist of initialization section only, that does the necessary binding code. They allow to avoid code within "start application" routine across different projects. At the same time they keep the actual library units free of initialization.

I have 1 common routine which is called from all my projects. It accepts an enumeration to decide what parts to start.

I guess this is your 'binding' unit idea, except it doesn't have an initialization section...

Michael.

Graeme Geldenhuys
to Dmitry Boyarintsev: On Thu, Mar 31, 2016 at 11:28 AM, Graeme Geldenhuys < One could use an alternative…
Dmitry Boyarintsev wrote
One could use an alternative approach and have "binding" units. The unit would consist of initialization section only, that does the necessary binding code.

tiOPF's TestSuite project has a tiTestDependencies.pas unit which primarily consists of a large uses clause and a procedure called tiRegisterTests

eg:

procedure tiRegisterTests;
begin
  ...snip...
  GTIOPFManager.DefaultOIDGenerator:= TtiOIDGeneratorForTesting.Create;
  tiBaseObject_TST.RegisterTests;
  tiUtils_TST.RegisterTests;
  tiRTTI_TST.RegisterTests;
  ...snip...
end;

Each *_TST.pas unit defines a global RegisterTests() method than needs to be called before that unit is activated.

In the framework side we have a unit that registers various logging output formats. Again a tiLogReg.pas unit is used, but this time its inititialization section activates all the dependency logging classes. This whereas with the test framework the tiRegisterTests procedure needed to be called, with the tiLogReg you just need to have it somewhere in your program unit's uses clause.

========================
unit tiLogReg;
{$I tiDefines.inc}
interface

implementation
uses
tiLog
// ,tiConstants { ToDo: We should move log constant to this unit. } ,tiCommandLineParams
,tiLogToFile
,tiLogToGUI
,tiLogToConsole
;

initialization
  if gCommandLineParams.IsParam(csLog)
  or gCommandLineParams.IsParam(csLogVisual) then
    GLog.RegisterLog(TtiLogToFile.Create);
  if gCommandLineParams.IsParam(csLogVisual) then
    GLog.RegisterLog(TtiLogToGUI.Create);
  if gCommandLineParams.IsParam(csLogConsole) then
    GLog.RegisterLog(TtiLogToConsole.Create);

========================
Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Michael Van Canneyt
to Maciej Izak: 2016-03-31 17:06 GMT+02:00 Michael Van Canneyt : It is mostly for initialization "class…
Maciej Izak wrote 10 lines
2016-03-31 17:06 GMT+02:00 Michael Van Canneyt : > I imagine so, yes. > > It is one of the reasons why I don't really see the usefulness of this > construct, except that it looks OOP-ish. > > It is mostly for initialization "class var" related stuff inside records and classes. Very usefully especially with generics.

Ahhhhh.. Damn generics, pain in the **** :)

Michael.

Sven Barth
to Graeme Geldenhuys: [my personal opinion - feel free to ignore this paragraph] I hate such "features" pulled…

Am 31.03.2016 17:28 schrieb "Graeme Geldenhuys" <

Show quoted text 13 lines
: On 2016-03-31 16:06, Michael Van Canneyt wrote: > I am guessing it comes from C++/Java/C#, which AFAIK do not have > the 'initialization' section. But that's just a guess. [my personal opinion - feel free to ignore this paragraph] I hate such "features" pulled in from other languages, when Object Pascal already had perfectly good solutions (Object vs Record with Methods is another example). It really feels like it is polluting the Object Pascal language.

Class constructors allow for a closer coupling between classes and their initialization and as Maciej said: for generics there is not really another way as the specializations are more or less everywhere (though with generics that doesn't currently work correctly anyway, but that's on my todo list).
(analogous for class destructors)

Regards,
Sven