I have inherited a large code base that is full of constructs like this:
try
DoWhatever;
finally
end;
Sometimes "DoWhatever" involves some fiddling with controls, and very often it's a post to a database, and there are many cases in the code where there IS something in the finally block.
But my understanding is, if there's nothing in the finally block, then the whole try...finally thing is pointless. The code is pretty noisy overall so I'm assuming it was just a placeholder for future code or a holdover from previous code. (There are many placeholders in the code.)
Is my understanding correct or is there some secret double-bluff reverso in Delphi try...finally blocks I've overlooked? (This is Delphi 2010.)
There is no functional purpose to it — it has no effect on the run-time behavior of the program. When control leaves the try section, the program will jump to the finally section, do nothing, and then continue to whatever the next instruction should be (according to how control reached the finally statement), the same as if the try-finally block hadn't been there at all. The only difference will be that the program spends an extra moment before and after the try-finally block as it sets up and clears the control structure form the stack.
It might be that the author had a template that included a try-finally block, but that some instances of that template ended up not needing any cleanup code. Having the code fit a consistent pattern might have made certain automated tasks easier.
The try-finally block might also provide a convenient place to put a breakpoint that triggers after the protected code runs, even in the event of an exception or other premature termination.
To find out why the code has such apparently useless constructs, ask the previous author, or check the commit history.
Related
I think this must be a FAQ, but googling hasn't really helped.
What may I do - and may do not - in FormCreate()?
I am wondering if all of the form's child controls are fully created and available for access, etc.
The reason I ask is that I stumbled over an old project where my FormCreate() simply consists of
Sleep(1000);
PostMessage(Handle, UM_PROGRAM_START, 0, 0);
It seems that I want to "wait a bit" and then do some initialization "when things have settled down" ...
Surely I had a reason for it at the time(?), but, in the absence of an enlightening comment I am unable to recall why I felt that to be necessary.
Can anyone state, or reference a link which states, any restrictions on what one may do in FormCreate()?
[Update] I think thta DavidHefferman found the solution when he wrote "the application starts pumping messages. That happens when you call Application.Run in your .dpr file".
I guess that I wasn't concerned about a single form. For instance, my main form wants to do somethign with my config/options form at start up, so obviously would have to wait until it is created.
Here's a typical .DPR from one of my projects ...
Application.Initialize;
Application.CreateForm(TGlobal, Global);
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TLoginForm, LoginForm);
Application.CreateForm(TConfigurationForm, ConfigurationForm);
//[snip] a bunch of other forms ...
Application.Run();
So, it makes sense for my app's mainForm.CreateForm() to send a UM_APPLICATION_START to itself which it won't process until all forms are created & initialized (or, I could just call the fn() which the message triggers from my .DPR after Application.Run() is called; but I prefer the message as it is more obvious - I rarely look at my .DPR files).
There's no definitive documentation giving the list of all the things you can do and connot do in a form's OnCreate.
As for whether or not the .dfm file has been processed and all the form's owned components created, yes they have.
I wouldn't place much store in the code you have found. Calling Sleep during start up, to make the main thread wait, is absolutely not good practice. If the code wanted to wait for another thread it could block for that thread, or wait to get a message from that thread. This just looks like code that got put in by someone who didn't understand what he/she was doing. And the code never got removed.
The other line of code is reasonable:
PostMessage(Handle, UM_PROGRAM_START, 0, 0);
Because this message is posted, it won't get processed until the application starts pumping messages. That happens when you call Application.Run in your .dpr file. Which means that everything related to the creation of you main form happens before that message is pulled off the queue.
I wouldn't put to much initialization code in FormCreate, instead I would place it into a separate function, like
fm := TForm.Create;
fm.Init;
The problem is, an exception thrown in the FormCreate() procedure is not re-thrown (there is only a MessageBox). That means, your code keeps running, although the form is not initialized correctly.
You may do whatever you want in the FormCreate. But there is no message handler to play with, that's all. In general I would create dependent objects in the FormCreate and free them in the FormDestroy. I would also try to avoid time consuming initialization routines.
Some part of my source code are nested inside try statements in order to handle some run time errors, at the same time each and every line must be tried to execute even if the previous line is not executed because of run time error .
currently my code looks like this
try
try
//statement1
except
end;
try
//statement2
except
end;
try
//statement3
except
end;
finally
//something
end;
I am very sure going in the wrong way ,even if the final out put is working well, I have to do this for dozens of lines.
Is there any better way to implement this
If you want each statement to execute then you have to write it the way you have done. Note that in that case may not need the try/finally because you are swallowing all the exceptions.
However, the code does look a bit odd to me. I wonder if you really need each and every statement to execute. Normally you would write:
try
statement1;
statement2;
statement3;
except
//handle exceptions
end;
Then, if there is an exception in statement1, the other two lines will not execute.
However, it would be even more common not to handle exceptions at all and let them float up to some higher level handler. If you are making routine logic decisions using exceptions then that would be considered bad practice.
I think it would be helpful for you to publish some of your code that handles the exceptions and some details of what exceptions you are expecting to occur. Then we could give you some more specific advice.
I am converting a low level C library to Delphi.
I find a lot of casts. I think it is normal in C World. I think I am safe in throwing them out. Integer is 32 bit only here. What do you think?
What could be the overhead of OOP if I convert it to objects etc?
Similarly I want to know the cost of try .. finally and exceptions.
Give me any tip that you think would be useful.
3 Similarly I want to know the cost of try .. finally and exceptions.
The cost of a try ... finally is negligable except in tight loops (put them around and not in the loop). Use them liberally to protect all your resources by balancing all instantiations / opens / allocations with free's / closes / de-allocations.
<code-to-open-a-file>
try
...
finally
<code-to-close-the-file>
end;
The cost of a try ... except is noticeably higher. Use them to respond to exceptions occuring, but only when you can actually take some meaningful action like counter acting the reason for the exception, logging some specific information that would be lost at a higher level in your app, etc. Otherwise let the exception propagate to the caller of your code so it can (eventually) be caught at a more general level.
Never let exceptions escape your application or library or any thread within it.
Never "eat" exceptions by having an empty except block:
try
...
except
end;
There really is only one type of situation where this makes sense: catching exceptions in code that logs exceptions... And then always add a comment to say why you are eating the exception.
You may find some helpful suggestions in the answers to this question on SO:
Best resources for converting C/C++ dll headers to Delphi?
You may also want to take a look at the C-To-Pas project which aims to automate much of the conversion from C to Delphi.
Moving from a procedural language to OOP is a big leap. There are many advantages of using OOP. OOPs are easier to code and maintain. Choosing Delphi PL is a good choice because it can also access at low level by inserting assembly codes. Try-catch is used to prevent program crashes at run time because of exceptions.
Is there a place where I can add code that will be executed before unit initialization?
The reason I want to do this is I need to change the DecimalSeparator, this has to be done before the initialization of some units. I have put it in the project source, before Application.Initialize but it is too late by then.
As I see it the only choice I have is to put it in the initialization of the unit that needs the DecimalSeparator to be changed, is this the case?
Thanks in advance for any advice.
Initialization order in Delphi is deterministic: units get initialized in the same order as the compiler compiled them, and finalized in the reverse order. The compiler starts at the top of the DPR's uses clause and works its way down, and for each unit it finds, it does the same thing recursively: start at the start of the uses clause, try to compile each used unit that isn't already compiled, then compile the current unit. So if you can get your unit in before any of the other ones get compiled, then it will get initialized first.
If you want to make sure it gets executed first, make a new unit, put your changes in that unit's initialization block, and then make sure it ends up in the DPR before any of the units that will depend on the changes. You might even want to make it the first unit, unless you have other "must be first" units there already, such as replacement memory managers.
Put it into the initialization section of the first unit in your project uses list, that way it will be executed prior to any other initialization code.
A word of warning here.
I've got an application running on the desktop of a logged in user and IN THE MIDDLE of testing the app the DecimalSeparator changed for me, without me restarting the application.
I used to set the
DecimalSeparator := '.';
once in the FormCreate() code, but that seems not the be enough. So now I set it once every time before I use my FormatFloat() function (used only in one place in my application).
I do not know WHY this happens, but probably there are some system-wide parameter changes happening, that reset the char to ',' on my system.
The best way to avoid this is probably to set the decimal separator in windows configuration to '.' to avoid strange problems...
When I'm debugging something that goes wrong inside a loop, say on the 600th iteration, it can be a pain to have to break for every one. So I tried setting a conditional breakpoint, to only break if I = 600. That works, but now it takes almost a full minute to reach that point, where before it was almost instantaneous. What's going on, and is there any way to fix it?
When you hit a breakpoint, Windows stops the process and notifies the debugger. It has to switch contexts, evaluate the condition, decide that no, you don't want to be notified about it, restart the process and switch back. That can take a lot of processor cycles. If you're doing it in a tight loop, it'll take a couple orders of magnitude more processor cycles than one iteration of the loop takes.
If you're willing to mess with your code a little, there's a way to do conditional breakpoints without incurring all this overhead.
if <condition here> then
asm int 3 end;
This is a simple assembly instruction that manually sends a breakpoint notification to the OS. Now you can evaluate your condition inside the program, without switching contexts. Just make sure to take it out again when you're done with it. If an int 3 goes off inside a program that's not connected to a debugger, it'll raise an exception.
It slows it down because every time you reach that point, it has to check your condition.
What I tend to do is to temporarily create another variable like this (in C but should be doable in Delphi).
int xyzzynum = 600;
while (true) {
doSomething();
if (--xyzzynum == 0)
xyzzynum = xyzzynum;
}
then I put a non-conditional breakpoint on the "xyzzynum = xyzzynum;" line.
The program runs at full speed until it's been through the loop 600 times, because the debugger is just doing a normal breakpoint interrupt rather than checking conditions every time.
You can make the condition as complicated as you want.
Further to Mason's answer, you could make the int 3 assember only be compiled in if the program is built with the debug conditional defined:
{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
asm int 3 end;
{$endif}
So, when you are debugging in the ide, you have the debug conditional in the project options. When you build the final product for your customers (with your build script?), you wouldn't include that symbol, so it wont get compiled in.
I also included the $message compiler directive, so you will see a warning when you compile letting you know that the code is still there. If you do that everywhere you use int 3, you will then have a nice list of places which you can double click on to take you straight to the offending code.
N#
Mason's explanations are quite good.
His code could be made a bit more secure by testing that you run under the debugger:
if (DebugHook <> 0) and <your specific condition here> then
asm int 3 end;
This will not do anything when the application is running normally and will stop if it's running under the debugger (whether launched from the IDE or attached to the debugger).
And with boolean shortcut <your specific condition here> won't even be evaluated if you're not under the debugger.
Conditional breakpoints in any debugger (I'm just surmising here) require the process to flip back and forth every time between your program and the debugger every time the breakpoint is hit. This process is time consuming but I do not think there is anything you can do.
Normally condition breakpoints work by inserting the appropriate break instruction into the code and then checking for the conditions you have specified. It'll check at every iteration and it might well be that the way in which the check is implemented is responsible for the delay as it's unlikely that the debugger compiles and inserts the complete check and breakpoint code into the existing code.
A way that you might be able to accelerate this is if you put the condition followed by an op with no side effect into the code directly and break on that op. Just remember to remove the condition and the op when you're done.