 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
swansnow Guest
|
Posted: Wed Sep 28, 2005 2:55 pm Post subject: newbie: deactivate query before freeing? |
|
|
Do you have to deactivate a query before you free it? Does this
guarantee that the database server will close the connection or
something like that?
What about the use of try..finally? Is this necessary?
try
myQuery.Create(nil);
myQuery.sql.text := 'SELECT * from Blah';
myQuery.active := true;
...
finally
if assigned(myQuery) then
begin
myQuery.active := false;
freeAndNil(MyQuery);
end;
-Corinna
|
|
| Back to top |
|
 |
swansnow Guest
|
Posted: Wed Sep 28, 2005 2:58 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
| Quote: | myQuery.Create(nil);
sorry, that should be myQuery := TQuery.create(nil); -- of course  |
-Corinna
|
|
| Back to top |
|
 |
Maarten Wiltink Guest
|
Posted: Wed Sep 28, 2005 5:43 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
"swansnow" <schultz (AT) harlingen (DOT) isd.tenet.edu> wrote
| Quote: | Do you have to deactivate a query before you free it? Does this
guarantee that the database server will close the connection or
something like that?
|
Query components usually operate on connection components. If you
want to close the connection, close the connection component.
Any reasonable component should clean up after itself on being freed.
If you find one that doesn't, don't use it. There are plenty that do.
| Quote: | What about the use of try..finally? Is this necessary?
|
Sometimes. Specifically, when an exception happens in the try block.
The point is that you never know when it will be necessary, so you
guard against it all the time.
| Quote: | try
myQuery.Create(nil);
myQuery.sql.text := 'SELECT * from Blah';
myQuery.active := true;
...
finally
if assigned(myQuery) then
begin
myQuery.active := false;
freeAndNil(MyQuery);
end;
|
While this works, it's not the usual idiom.
Create
try
Work
finally
Free
end;
You are explicitly _not_ guarding against an exception in Create.
Instead, you are making sure that *if* the Create succeeded, there
*will* be a Free.
Also, you don't need to check that the object is Assigned to call
Free on it. Free checks that; that's what it's for.
Groetjes,
Maarten Wiltink
|
|
| Back to top |
|
 |
swansnow Guest
|
Posted: Wed Sep 28, 2005 11:37 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
How about:
myQuery := TQuery.create(nil);
try
myQuery.sql.text := 'select * from blah';
...
finally
freeAndNil(myQuery);
end;
See if I'm right:
This way, if the Create failed, then myQuery is an invalid reference,
and trying to use it will result in an exception, in which case, it
will be assigned nil, but the exception will still be thrown. If the
Create succeeded then the query will execute and so forth. If an
exception occurs in the "try" code, the reference will be freed, and
then the exception will be thrown. If no exceptions are generated, the
reference still gets freed, and everything's fine.
In addition you're saying that the following code is ok:
myQuery := nil;
freeAndNil(myQuery);
But the following code isn't ok?
myQuery := nil;
myQuery.free;
Do I have it right?
-Corinna
|
|
| Back to top |
|
 |
Maarten Wiltink Guest
|
Posted: Thu Sep 29, 2005 8:53 am Post subject: Re: newbie: deactivate query before freeing? |
|
|
"swansnow" <schultz (AT) harlingen (DOT) isd.tenet.edu> wrote
I'm going to do this in small steps now, after having OE crash on me
three bloody times in a row, the last time as I was typing the final
word before signing off.
| Quote: | How about:
myQuery := TQuery.create(nil);
try
myQuery.sql.text := 'select * from blah';
...
finally
freeAndNil(myQuery);
end;
|
Yes, that's right.
Groetjes,
Maarten Wiltink
|
|
| Back to top |
|
 |
Maarten Wiltink Guest
|
Posted: Thu Sep 29, 2005 9:02 am Post subject: Re: newbie: deactivate query before freeing? |
|
|
"swansnow" <schultz (AT) harlingen (DOT) isd.tenet.edu> wrote
[...]
| Quote: | See if I'm right:
This way, if the Create failed, then myQuery is an invalid reference,
and trying to use it will result in an exception, in which case, it
will be assigned nil, but the exception will still be thrown.
|
No, that's not what happens.
Let's distinguish first between an "invalid" and a "useless" reference.
There is exactly one invalid reference, the null pointer, nil. That's
a useful thing for a function to return in case of problems, but the
code that calls the function then needs to check the return value
before using it. Every time. This can be a bit of a chore.
Incidentally, constructors are magic and can't return nil without outside
help or major hackery.
Any dangling pointer is a useless reference. A function should never
return a dangling pointer in any case, but certainly not without making
it clear through other means (another Boolean parameter for example) that
the value isn't valid.
More commonly, a failing constructor will raise an exception. This will
abort the normal flow of execution and start handling the exception
instead. The nearest enclosing try statement (whether try-except or
try-finally) will be located and its handler clause entered. If it is
necessary for this to abort and leave any procedures, this is done. No
code in the procedure will be executed, there will be *no return value*
from functions, and your assignment above (snipped) doesn't happen. Nor
does the code after it; it needs to be an _enclosing_ try statement.
Exception handling only stops in an except clause that handles the
exception (and does not reraise it), or when the exception leaves your
program altogether. The latter ends your program.
| Quote: | If the Create succeeded then the query will execute and so forth. If
an exception occurs in the "try" code, the reference will be freed,
and then the exception will be thrown. If no exceptions are generated,
the reference still gets freed, and everything's fine.
|
Yes.
Groetjes,
Maarten Wiltink
|
|
| Back to top |
|
 |
Maarten Wiltink Guest
|
Posted: Thu Sep 29, 2005 9:05 am Post subject: Re: newbie: deactivate query before freeing? |
|
|
"swansnow" <schultz (AT) harlingen (DOT) isd.tenet.edu> wrote
[...]
| Quote: | In addition you're saying that the following code is ok:
myQuery := nil;
freeAndNil(myQuery);
But the following code isn't ok?
myQuery := nil;
myQuery.free;
Do I have it right?
|
Er, no. Sorry. Free is *always* safe. I think I said that, but I'm too
lazy to go back and check. FreeAndNil adds no magic, just the convenience
of freeing and clearing an object reference in a single statement.
The unsafe one is Destroy, the destructor. Trying to destroy anything
but a valid object reference is an instant access violation.
Groetjes,
Maarten Wiltink
|
|
| Back to top |
|
 |
swansnow Guest
|
Posted: Thu Sep 29, 2005 1:48 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
| Quote: | Free is *always* safe. I think I said that,
|
Yes, you did... I've been quite confused on this issue for several
reasons: my background is C, where you have to be alert to
dereferencing pointers to memory you shouldn't access; the Delphi help
is confusing (quoted below, and then another comment by me)...
To me, saying myQuery.free, means "go to the object referred to by
myQuery and call the free method on it". Well if myQuery is nil, then
it doesn't refer to anything, so you can't dereference it. I see now
that free is special, so it's ok, you don't have to explain anymore
However, to make sure that the memory gets freed, you would have to
call Free before you assign nil. (Either way, though, you won't get an
exception.)
{QUOTE follows}
procedure FreeAndNil(var Obj);
Description
Use FreeAndNil to ensure that a variable is nil after you free the
object it references. Pass any variable that represents an object as
the Obj parameter.
Warning: Obj must be an instance of a TObject descendent class..
Procedure Free;
Use Free to destroy an object. Free automatically calls the destructor
if the object reference is not nil. Any object instantiated at runtime
that does not have an owner should be destroyed by a call to Free so
that it can be properly disposed of and its memory released. Unlike
Destroy, Free is successful even if the object is nil; so if the object
was never initialized, Free won't result in an error. ...
To free a form, call its Release method, which destroys the form and
releases the memory allocated for it after all its event handlers and
those of the components it contains are through executing.
{End QUOTE}
This seems to tell me a couple of things:
1) You have to free before you nil, in order to release the memory.
Calling free on a nil pointer will not result in an error, but the
object's memory won't get freed, since you lost the reference to it
when you assigned nil.
2) FreeAndNil is a shortcut that does the freeing and nil-ling in to
proper order, in a single statement.
3) If you Free a form, the memory won't actually get released (because
the components won't get freed?), so you should say Release, and then
nil.
Maybe I have it now? :)
-Corinna
|
|
| Back to top |
|
 |
Maarten Wiltink Guest
|
Posted: Thu Sep 29, 2005 3:00 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
"swansnow" <schultz (AT) harlingen (DOT) isd.tenet.edu> wrote
[...]
| Quote: | To me, saying myQuery.free, means "go to the object referred to by
myQuery and call the free method on it". Well if myQuery is nil, then
it doesn't refer to anything, so you can't dereference it. I see now
that free is special, so it's ok, you don't have to explain anymore
|
If you'll bear with me for a few more sentences...
Free isn't actually that special. It checks that 'Self' ("this", to C++
types) isn't nil before proceeding. Any method is free to do that. All
my primary property accessor methods do it. Evaluating a property on a
null object returns a default value, setting the value is simply ignored.
The latter is exactly what Free does.
Evaluating a property, or calling a method, on a null object, is in fact
permitted - sometimes. If you're careful, mostly. The reason is that
you don't "go to the object" in all cases. For virtual methods, you do.
For static methods however, the object's declared type determines which
method will be called. Even if the actual object is a derived type, and
the derived type redefines the method, the original method will be
called. Remember that the method was static; it cannot be overridden.
So for static methods, the call is resolved at compile time. The object
reference doesn't come into it and may even be nil. It is only used as
the first, implicit parameter to the call.
<snip quote from the help file>
| Quote: | This seems to tell me a couple of things:
1) You have to free before you nil, in order to release the memory.
Calling free on a nil pointer will not result in an error, but the
object's memory won't get freed, since you lost the reference to it
when you assigned nil.
|
That would be rather a silly mistake to make - not that any of us are
above silly mistakes, of course. But your fingers will learn in short
order that ".Free" comes before ":=nil".
BTW, if freeing a variable is the last thing you do with it, you don't
need to clear it. The compiler will even warn you that the assignment
is moot. With a little discipline, most clearing of variables can be
dispensed with.
[...]
| Quote: | 3) If you Free a form, the memory won't actually get released (because
the components won't get freed?), so you should say Release, and then
nil.
|
Components introduce the "Owner" scheme, where the owning component
will free any components it owns when it's freed itself. Forms are
components and freeing a form will free any components you've designed
onto it.
Release has a different function. You need it when you want to free a
form from one of its event handlers. Since event handlers may be called
in response to Windows messages, and more messages may be queued, more
event handlers may be called after this one. Release defers the actual
freeing until all pending messages have been processed - it does this,
of course, by posting a message to the end of the queue itself, to
which the form responds by falling on its sword.
The truth is that _freeing_ a form from one of its event handlers is
almost universally a bad idea. You might as well close it, and figure
out what to do in the OnClose handler. If you set Action to caFree,
the form will find its own way. One of those ways does in fact call
Release, but that's an internal matter. Release never needed to be
public IMO.
| Quote: | Maybe I have it now?
|
Umm.... Don't hold your breath. (-:
(That's a *good* thing. Never stop learning.)
Groetjes,
Maarten Wiltink
|
|
| Back to top |
|
 |
swansnow Guest
|
Posted: Thu Sep 29, 2005 8:57 pm Post subject: Re: newbie: deactivate query before freeing? |
|
|
You've been very patient with me, Maarten. Thank you! Those of us who
are still learning need people like you to help us out...
(Which is to say, everyone needs someone who has more of a clue than
they do!)
-Corinna
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|