Re: Record type flushing
From: Rob Kennedy (me3_at_privacy.net)
Date: 04/08/04
- Next message: Skybuck Flying: "Re: the garbage collector"
- Previous message: Skybuck Flying: "Re: Evaluating Exceptions, Try Except and Try Finally"
- In reply to: AlanGLLoyd: "Re: Record type flushing"
- Next in thread: AlanGLLoyd: "Re: Record type flushing"
- Reply: AlanGLLoyd: "Re: Record type flushing"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Thu, 08 Apr 2004 12:44:12 -0500
AlanGLLoyd wrote:
> I'm just trying to get my mind round the use of "reference-counted
> fields" (AIUI these are essentially from interfaces / AX / COM) and
> storage in records. I would associate storage in records with
> isolated values which do not depend on items external to the records.
> Or are "reference counted fields" in records just a more complex use
> of records ? Could you explain a little.
Reference-counted fields include strings, interfaces, dynamic arrays,
and any structured types -- arrays and records -- that contain
reference-counted fields. (Yes, it's a recursive definition.) I prefer
the terms "managed" or "compiler-managed" instead of "reference-counted"
since both AnsiStrings and WideStrings need special handling, but
WideStrings aren't reference-counted. All the above types have special
code inserted by the compiler when you use them.
> What could be the effect of not using New() for allocating memory for
> records ?
If you use GetMem to allocate your record, then memory contents will be
random. If you try to assign a new value to a string field in that
record, the compiler will insert its normal string-handling code, which
decreases the reference count on a non-empty string before assigning a
new value. The record doesn't really contain any valid strings (since it
was only just allocated), but the compiler doesn't know that. The random
value that GetMem left in the string field looks like a valid string
reference, so the compiler's code tries to release that reference before
assigning the new one. That quickly leads to an access violation.
The Initialize procedure can be used to solve that problem. Initialize
will go through each of the record's fields recursively, setting any
managed fields to their "empty" values -- the values that ensure that
nothing tries to delete them when assigning a new value -- *without*
trying to interpret the previous values as valid references. String
fields will be set to '', and interfaces will be set to nil. However,
any unmanaged fields should retain their initial "random" values. In
effect, it's the same as if you had declared the record on the stack.
The values are initialized the same way as normal local variables.
The New procedure is conceptually equivalent a call to GetMem
immediately followed by a call to Initialize. Likewise, Dispose is the
same as Finalize + FreeMem. The Finalize procedure destroys any managed
fields in the record, but it does not necessarily set those fields'
values to their "empty" states. The assumption is that the next thing
you're going to do is free the memory anyway, so there's no point in
setting values that will never be read again.
The AllocMem function is the same as a call to GetMem followed by
FillChar(0). In practice, it ends up yielding even better results than
New since all the fields in the record are zeroed, not just the managed
ones. However, there is nothing formally defining the managed fields'
empty values as being the same as zeroed values. There is nothing
requiring that an empty string or array must be represented internally
by a nil pointer. That's just an implementation detail. Therefore, to be
on the safe side, I recommend calling Initialize, even on variables
allocated with AllocMem.
Since New and Dispose are available, there typically isn't any need for
Initialize and Finalize. Where they come in handly is on memory
allocated from something other than Delphi's built-in memory-management
functions. If you're using the shell's memory manager, or calling the
heap API functions, then Initialize and Finalize should also be there.
-- Rob
- Next message: Skybuck Flying: "Re: the garbage collector"
- Previous message: Skybuck Flying: "Re: Evaluating Exceptions, Try Except and Try Finally"
- In reply to: AlanGLLoyd: "Re: Record type flushing"
- Next in thread: AlanGLLoyd: "Re: Record type flushing"
- Reply: AlanGLLoyd: "Re: Record type flushing"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|