When a TForm is created in Builder (or Delphi) code is added to main to create these forms at application launch:

Application->CreateForm( __classid( TxForm), &xForm );

this makes things easier, but is it wise when the applications has 10, 20, 50, 100 forms? I am assuming that this can grab all kinds of memory and system handles. The form can always be created on the fly when needed by removing it using the Project->Options->Forms dialog and:

Of course, you can make Delphi not autocreate the forms in question by removing them from the list of autocreate forms at Project >> Options >> Forms. You probably already know that but I thought it should be mentioned with the question.
–
Muhammad AlkarouriNov 10 '10 at 20:57

Correct, I will add that to the question for clarity.
–
Gregor BrandtNov 10 '10 at 21:10

5 Answers
5

Forms that are created but not yet visible take memory and make impact startup time but shouldn't use any system handles, since stuff like window handles aren't allocated until the window is actually shown.

With that said, I almost always create forms manually (using code similar to your auto_ptr), because I can't stand having global variables. Creating forms manually gives a few advantages: faster application startup, forms are always displayed in a known good state, and easier to switch later to showing multiple instances of a form at once if you need to.

As the VCL documentation explains, deleteing a form directly (or indirectly, by using a stock std::auto_ptr) may cause memory errors, since the form may have unprocessed messages. To avoid this problem, I wrote two smart pointer classes that takes care of calling Release instead of delete. You can download them from http://gist.github.com/671452.

If you look at the source code for Release, it calls PostMessage(Handle, ...), and reading the value of the Handle property calls HandleNeeded, which allocates a handle (i.e., allocates a bunch of Windows resources needed to show the form on screen). It seems silly to me, for a form that was never shown or whose window handle has since been destroyed, to allocate a handle just so you can immediately release it. Calling delete if !HandleAllocated is a micro-optimization, but it's never caused me any problems.
–
Josh KelleyNov 10 '10 at 22:57

4

If you read the VCL documentation more closely, it says: "Any event handlers for the form or its children should use Release instead of Free (Delphi) or delete (C++). Failing to do so can cause a memory access error." An event handler for the form needs to use Release() instead of Free() or delete, but any other code not called from within the context of the form's event handlers can safely use Free() or delete without worrying about "memory errors".
–
Remy LebeauNov 11 '10 at 1:11

The same document, as linked above, also has this explicit line: Use Release to destroy the form and free its associated memory. So, we still have to use Release, but not because of possible memory errors?
–
Gregor BrandtNov 11 '10 at 1:47

It really depends of how you use the forms in your application. I usually create them on the fly when needed and then free them when I'm done. It's more manual work but saves resources (and costs a little bit of CPU every time which can cause delays).

If you rarely use a form, I'd say create/free(delete) manually when needed but if you use the form all the time and for the whole life of the app, stay with the default way.

Suggesting to let the IDE "do it its own way" implies that the IDE is employing some kind of intelligence to the way it generates code for creating forms and data modules. It isn't. It's just creating what you told it to create, and in the order you told it to use. If you didn't explicitly tell it what to do via the project-options dialog, then it's just creating things in the order you added them to your project. The IDE does not know any better than you do.

Using auto-created forms and data modules encourages the use of the global variables that the IDE declares for you to refer to those objects. You don't need them.

Auto-create only your main form. When you need anything else, create it yourself using the typical way of creating objects: Call the constructor, and store references to the objects in local variables or fields of your other objects, not the IDE-provided globals, which you should delete. Don't bother with CreateForm. I wrote an article explaining why.