Solved

Order of unit initialization. Any clues?

Posted on 2001-07-25
16
510 Views
Last Modified: 2010-04-06
Well, I have a rather big project, with several (read lots of) units using each other.
Everything was fine until I tried to switch to RT libs.

Scaled down description:
Unit A contains some base classes, and some _global_ initialization code required by them. The code resides in the initialization section.
Unit B contains some class derivated from those in Unit A and in the initialization section makes use of the global data inited in Unit A. Since Unit A is listed in the uses clause of Unit B, this should be no problem (or would it?)

Anyway, the whole scheme was OK until I tried to switch the project to RT libraries. After I did that (build all, the whole treat), Unit B weirdly gets to be inited _before_ Unit A and this produces an error since the global init didn't happen yet at that time.
If I touch then Unit B (e.g. enter one benign space in the source) and run the project again, it performs well. However, when switching back to embedded libs (again with build all) it fails in the same way until I touch again Unit B.

By switching to RTlibs I mean nothing more than checking the appropriate box in Project's Options/Packages tab and then "Build all" from Project menu.

It's a C/S D3.

Did anyone encounter any similar behavior? Any suggestions? Any workarounds? (Pls, don't tell me to upgrade :) )

F.
0
Comment
Question by:fva
  • 8
  • 5
  • 3
16 Comments
 
LVL 27

Accepted Solution

by:
kretzschmar earned 100 total points
ID: 6316486
sounds more like a naming conflict,
maybe the RTLib has a unit which has the same name as unitA
0
 
LVL 4

Author Comment

by:fva
ID: 6316758
Maybe I was too acronymic :)

RTlibs stands for runtime libraries and I'm talking for the moment only about the default libs from Delphi (I even removed everything from the line below the checkbox, except for the bare minimum - vcl30, vclx30, and such ...).

Anyway, it's a possible idea and I'll check into that.

Thanks,
Florin
0
 
LVL 4

Author Comment

by:fva
ID: 6316847
Well, I did check.

Sadly (for me at least), there is only one unit with that name (the right one) and moreover, there is no file containing that name neither in Delphi dir nor in my common projects dir, except of course for the legitimate ones, part of the project in cause.
The "A" and "B" units are used only by this project and are not included in any package (at least not yet).

F.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6317306
Perhaps you should upgrade...

Oooooops - I wasn't supposed to say that! So I take it back. I'm sorry. Please accept my apologize...   :-))

Regards, Madshi.
0
 
LVL 4

Author Comment

by:fva
ID: 6317955
Well, I know I'm three versions behind, but I always like better the devil I know.
One sunny day I'll consider upgrading, too. Until then I'll rather work around a workaround :)

F.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6318087
:-)
0
 
LVL 4

Author Comment

by:fva
ID: 6318302
Hi all.

I just remembered a few things I already knew and I always keep forgetting :)

1. If you have a problem, try to describe it so that others can understand it and you'll get to solve it yourself in the process.
2. If you do not succeed as above and others cannot help you, you have overlooked some important part of the problem
3. 3rd party elements involved in the issue are the last to be suspected.

Now back to the question with details on the tricky cause I spotted:

Of course, I discovered there is unit C :)
Unit A uses Unit C, which in turn uses (in the appropriate section) Unit A and Unit B. So far, so good.
At startup time, Unit A is the first listed in the project and Delphi tries to evaluate its dependencies but probably marks it as "about to be initialized". In this process, Unit C gets to be started (A is not inited yet) and that would require starting Unit A and Unit B. Unit A is "about to be initialized", so Delphi skips it (to avoid a loop) and goes to Unit B. Unit B would like A to be inited, too, but for the same reason as above Delphi skips that, causing the problem described by myself in the question.

I couldn't ask Borland to solve such situations other way than it did (at least not in version 3 :) ) so I don't think it's a bug.

My solution (which seems to work) is to put Unit C first in the project and Unit A before Unit B in the "uses" clause of Unit C (not that it would matter much now).

Thank you both for bothering with this (each one its own way :) ).
Florin
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6318356
you could resolve this circular reference
by moving unit C into the implementation-section as  uses-clause
and also do the same with Unit C (moving Unit B)
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 6318367
just from the helpfile

When units reference each other directly or indirectly, the units are said to be mutually dependent. Mutual dependencies are allowed as long as there are no circular paths connecting the uses clause of one interface section to the uses clause of another. In other words, starting from the interface section of a unit, it must never be possible to return to that unit by following references through interface sections of other units. For a pattern of mutual dependencies to be valid, each circular reference path must lead through the uses clause of at least one implementation section.

In the simplest case of two mutually dependent units, this means that the units cannot list each other in their interface uses clauses. So the following example leads to a compilation error:

unit Unit1;

interface
uses Unit2;
...

unit Unit2;

interface
uses Unit1;
...

However, the two units can legally reference each other if one of the references is moved to the implementation section:

unit Unit1;

interface
uses Unit2;
...

unit Unit2;

interface
...
implementation
uses Unit1;
...

To reduce the chance of circular references, it?s a good idea to list units in the implementation uses clause whenever possible. Only when identifiers from another unit are used in the interface section is it necessary to list that unit in the interface uses clause.

meikl ;-)
0
 
LVL 4

Author Comment

by:fva
ID: 6319111
No Meikl, I'm afraid it's not that.

I have read several times your last comment, hoping that I missed something. I guess not. If still so, I will apologize.

I'm dissapointed and maybe a bit offended by your last comment (do not take me wrong, I do appreciate the intention to help).

Let me explain:
Such a circular ref is between the first things that hits fresh programmers in Borland's implementation of modularity. AFAIK it's caught by the compiler and cannot occur at runtime only. And since I'm still "hanging" on D3 then you might guess I've seen this before.
My issue was happening runtime. I'm sorry if my non-native English failed to underline that in the question, but I think my last comment was thorough enough (maybe too thorough?).

Well, I am sorry if my tone was by any means inappropriate, but please understand; when I saw that two heavy "Top15"'s are on my Q's thread I was kinda hoping for more.

One sad F.
0
 
LVL 4

Author Comment

by:fva
ID: 6319126
And Meikl gets the points, for the speed of the first post (which might have been even useful).
Thank you Madshi for the casual visit, too :)

F.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6319158
not at all florin,
this problem you have never happens personally to me,
and sorry that i nor madshi couldn't help you in this case

i have no idea yet, i could just shooting into the dark,
but i guess that you have this already done :-)

the only suggestion i have additional (shooting into the darkness) is
to split out the problmatic sections into a separat unit and add this new unit
into the uses clause of the others units

well, no idea

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6319172
oops, thanks :-)
0
 
LVL 4

Author Comment

by:fva
ID: 6319198
Well, now that's talking ("...to split out the problmatic sections..."). Personally I was looking for that kind of stuff rather than for quotes from help.

For the sake of any (poor) fellow that will eventually spend its points on this PAQ:

<speechmode>
"In the future I promise to design better the projects before starting coding. Thus I'll avoid messy references between units patched quickly without much thought during development."
"This particular problem was caused by an ill-designed hierarchy of classes and units, forced into shape merely by trial-and-error not by true preliminary thought."
</speechmode>

Yours,
F.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6319240
>> when I saw that two heavy "Top15"'s are on my Q's thread I was kinda hoping for more

Look, what you gave us was this:

Unit B references Unit A, while Unit A does NOT reference Unit B (or was it vice versa? doesn't matter).

When looking as those facts Delphi MUST initialize Unit A first, then thereafter Unit B. If Delphi doesn't do that, it's a crystal clear Delphi bug. Point. That's it. So what can even "heavy Top15's" do? Well, suggesting to upgrade, what I did. Well, it was more a joke, because you said you don't want to hear that, but in the end it was all I was able to say. What did you expect? Did you expect me to patch Delphi3 for you?  :-)

I mean the other way was so evident, that I didn't even felt the need to say it: Namely redesigning your unit initialization parts to work around that Delphi bug.

Regards, Madshi.
0
 
LVL 4

Author Comment

by:fva
ID: 6322568
I'm taking a course now on asking questions and... no, just kidding, but wouldn't that be a great course here in ExEx?
When I decide to ask something here it's usually either because I'm not in the mood to dig it out myself or because I want something like "second opinion" on something. (see one of my comments above on things forgotten/remembered)
I apologize if my description of the problem was clear only to me. Next time I'll Notepad it first, leave it on Desktop for a few days then read it again, rephrase and post. Really mean it. Well, maybe not days actually.

Anyway, nice chat. Shoots the boredom away from coding.

F.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video discusses moving either the default database or any database to a new volume.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now