Recent

Author Topic: Several units, one doesn't display output?  (Read 2868 times)

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Several units, one doesn't display output?
« on: October 18, 2017, 10:41:18 pm »
Newbie question regarding units: Three units each have a initialization section with a call to WriteLn (directly or via object method).

However, only two of the units create output:

Log message: Hi! From uAppData
Log message: Hi! From uProgSettings
Log message: Hi! From .lpr file


The last line is from the .lpr file.

However, there is no: "Log message: Hi! From uLogSimple1"? and also:
Code: Pascal  [Select][+][-]
  1. WriteLn('TLogS instance created');
doesn't produce output?

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Several units, one doesn't display output?
« Reply #1 on: October 18, 2017, 11:18:51 pm »
3 things i noticed (one responsible for your output)
- "LogS.TLogS.Create(AppData.ConfigFileWithPath);"afaik should read: "LogS := TLogS.Create(AppData.ConfigFileWithPath);"
- The above class also opens a file. It isn't closed on application end.
- last, you have an "end." at the line just above initialization of unit ulogsimple1, causing our initialization/finalization not to be compiled inside your code at all (it is simply ignored by the compiler).

If you have fixed that,and then run your code you'll receive an exception   :)

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: Several units, one doesn't display output?
« Reply #2 on: October 18, 2017, 11:20:35 pm »
In uLogSimple1 you have the line "end." before the initialization section. Since the "." signals the end of the file the initialization part is never executed-

If you put the "end." after the finalization keyword you will notice other issues:
The program does not compile because "LogS.TLog.Create(...)" is not a valid syntax. Use "LogS := TLogS.Create(....)" instead.
Now the program compiles, but crashes in the same line. If you place a breakpoint in this line, run the program and move the mouse over the "AppData" used in the Create call you will see that AppData is nil. Obviously, because AppData has not yet been initialized. The order in which the code in the initialization section of several units is executed depends on several things: the order of units in the "uses" line, whether a unit uses another one. To be honest I never was able to predict this execution order in a larger project. Therefore - very important! - NEVER write code which depends on the order of execution of the initialization section. Putting the creation of objects into the initialization is such a case. Don't do this. Instead, if you really need these global objects, create them in the project file, for example. And don't forget to Free them (this could also be done in the project file).

[EDIT] Ahhh, molly was faster...
« Last Edit: October 18, 2017, 11:24:47 pm by wp »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Several units, one doesn't display output?
« Reply #3 on: October 18, 2017, 11:28:03 pm »
Sorry for the cross wp (and only by a few seconds, really sorry).

At least you figured that appdata was not initialized already, i was still in the process of getting the executed order into mind.

Indeed as you write, (a) depends on (b) depends on (c) while at the same time (b) depends on (a). That is only 3 classes and already starting to become mind boggling.

edit: @mijen67
I understand what you're trying to do but afaik you won't be able to solve that puzzle. I once approached that with 'logging' to a memory stringlist first (you can also use an array of string for that), and only when the application is able to generate the correct filename it then writes the previous writes to the stringlist to file. I do that by declaring a global variable that contains the address of the log routine (that first writes to stringlist) and change that into the routine that directly writes to file at the moment the filename is known.
« Last Edit: October 18, 2017, 11:39:12 pm by molly »

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Several units, one doesn't display output?
« Reply #4 on: October 19, 2017, 12:23:13 am »
In uLogSimple1 you have the line "end." before the initialization section. Since the "." signals the end of the file the initialization part is never executed-

If you put the "end." after the finalization keyword you will notice other issues:
The program does not compile because "LogS.TLog.Create(...)" is not a valid syntax. Use "LogS := TLogS.Create(....)" instead.
Now the program compiles, but crashes in the same line. If you place a breakpoint in this line, run the program and move the mouse over the "AppData" used in the Create call you will see that AppData is nil. Obviously, because AppData has not yet been initialized. The order in which the code in the initialization section of several units is executed depends on several things: the order of units in the "uses" line, whether a unit uses another one. To be honest I never was able to predict this execution order in a larger project. Therefore - very important! - NEVER write code which depends on the order of execution of the initialization section. Putting the creation of objects into the initialization is such a case. Don't do this. Instead, if you really need these global objects, create them in the project file, for example. And don't forget to Free them (this could also be done in the project file).

[EDIT] Ahhh, molly was faster...

molly, wp,
Great! Thanks!
I've moved all object creation (+ more) into the project file, so that the order is clear (I hope).

Now I get a new issue. For some reason I can't create the log file, although the calls seem somewhat similar (i.e. in appdata.pas and in logsimple1.pas)?

mijen67

  • Full Member
  • ***
  • Posts: 130
  • It's hard to beat the bandwidth of a flying DVD
Re: Several units, one doesn't display output?
« Reply #5 on: October 19, 2017, 12:25:11 am »
edit: @mijen67
I understand what you're trying to do but afaik you won't be able to solve that puzzle. I once approached that with 'logging' to a memory stringlist first (you can also use an array of string for that), and only when the application is able to generate the correct filename it then writes the previous writes to the stringlist to file. I do that by declaring a global variable that contains the address of the log routine (that first writes to stringlist) and change that into the routine that directly writes to file at the moment the filename is known.

Perfect, that will solve the puzzle! Thanks!

 

TinyPortal © 2005-2018