ComboBox Help

22 views
Skip to first unread message

Gary Behan

unread,
Feb 15, 1998, 3:00:00 AM2/15/98
to

I was wondering if anybody could help me with a combobox question....

I am using a combobox to display all of the dialup entries on a computer.
The default selected on is being stored as a string in my registry settings.
How do I make sure that the displayed combobox item matches the stored
registry setting?

Thanks in advance

Gary

gbe...@SPAM-TRAPgci-net.com

** To reply by mail - remove the SPAM-TRAP from the above address **

Rodney E Geraghty

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

I'm assuming you already know how to read the string back from the registry
so you could use something like this to set the combobox:

ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(MyString);

Where MyString would be the string read from the registry.

Hope this helps!
--

Rodney E Geraghty
GERA-Tech
Ottawa, Canada
ger...@ibm.net

Gary Behan <gbe...@SPAM-TRAPgci-net.com> wrote in article
<34e7d...@news.gci-net.com>...

AlanGLLoyd

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

In article <34E90C87...@hawaii.edu>, Rod Gammon <gam...@hawaii.edu>
writes:

>Is there a function to check if a pointer is stale?
>

No, but the pointer should be set to nil by Delphi when you or Delphi frees the
memory. As it sometimes does not do this, it is good programming practice to
set the pointer to nil immediately after the memory has been freed.

Also, if you declare an object and there is a possibility of it not being used
(and especially if the object is declared in a procedure / function), you
should set it to nil soon after it it declared. When the object is declared,
Delphi _should_ set it to nil - but it doesn't always do it.

Alan Lloyd
alang...@aol.com

Duncan Murdoch

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

On 17 Feb 1998 09:39:49 GMT, alang...@aol.com (AlanGLLoyd) wrote:

>No, but the pointer should be set to nil by Delphi when you or Delphi frees the
>memory. As it sometimes does not do this, it is good programming practice to
>set the pointer to nil immediately after the memory has been freed.
>
>Also, if you declare an object and there is a possibility of it not being used
>(and especially if the object is declared in a procedure / function), you
>should set it to nil soon after it it declared. When the object is declared,
>Delphi _should_ set it to nil - but it doesn't always do it.

I'm not sure what you mean by "should" here. Are you saying that it
would be a good idea if Delphi did this, or are you saying that
there's something in the documentation that suggests it will, but it
sometimes doesn't? If the latter, I think you're wrong: as far as I
know there's nothing in the language definition that suggests Delphi
will ever set a pointer to Nil. The same is true about objects:
you're always free to set them to Nil, but Delphi won't do it
automatically.

There are two partial exceptions to this. One is for strings:
They're stored as pointers in D2+, and they are automatically set to
Nil when you enter a routine and when you clear the string, but I
wouldn't really call them pointers.

The other exception is for variables declared as static: they are
cleared to zero when the program loads. However, they aren't set to
zero when released, and local variables aren't set to zero when you
enter a routine.

In answer to the question about telling if a pointer is stale:
there's no way to do it based on looking at the pointer, unless you
use some programming convention that allows you to determine it.
Setting pointers to Nil when you release them sometimes works,
but often you'll have more than one pointer to the same object, and
it's tricky to find all the references to it to set to Nil when the
object is released.

Duncan Murdoch

AlanGLLoyd

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

In article <34e97d1...@news.ccs.queensu.ca>, dmur...@pair.com (Duncan
Murdoch) writes:

> (AlanGLLoyd) wrote:
>> When the object is declared, Delphi _should_ set it to
>> nil - but it doesn't always do it.
>
>I'm not sure what you mean by "should" here. Are you saying that it
>would be a good idea if Delphi did this, or are you saying that
>there's something in the documentation that suggests it will, but it
>sometimes doesn't?

Delphi 3 - Object Pascal Language Guide p10-13
"Because a Constructor always clears the storage it allocates for a new object,
all fields automatically have a default value of zero (ordinal types), nil
(pointer and class types), empty (string types), or Unassigned (the Variant
type)"

I have seen pronouncements on this newsgroup that objects declared in a
procedure / function do not always zero the allocated memory and pointers. I
have also seen discussion and advice which contained assertions about Delphi
setting freed memory pointers to nil. The advice to set the pointer of a freed
memory allocation to nil (to prevent any possible second attempt to de-allocate
the memory) seems sound to me.

The Delphi advice to call Free instead of Destroy in a Destructor, relies on
the Free method checking for non-nil before de-allocating the memory. There is
not much point doing such a check to protect _only_ against initialising
exceptions causing part allocated memory, when setting a freed pointer to nil
would cover _all_ second attempts to de-allocate memory.

What do the gurus say about this ?

Alan Lloyd
alang...@aol.com

Lloyd Budd

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

I'm no guru, but even in D1,

"When an object instance is created using th econstructor, the compiler
will ensure that every field in your object is initialized. You can
safely assume that all numbers will be initialized to 0, all pointers to
nil, and all strings to ''. (47, Pacheco and Teixeira, _Delphi
Developer's Guide 1st Edition_)

BUT that is only true for objects.

Lloyd Budd

Frederic GUILLIEN

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

I will just add that when you call the Free method, the variable (or
pointer) is never set to nil.
But it's completly true that all vars and pointers in a new object are
set to 0, nil, etc, it's inherited from the TObject class.

A dirty way to ensure that a pointer has a good reference is to use
try..except statement. And setting pointer to nil just after freeing the
memory is a very good rule.

Regards,

Frédéric GUILLIEN

David Ullrich

unread,
Feb 17, 1998, 3:00:00 AM2/17/98
to

AlanGLLoyd wrote:
>
> In article <34E90C87...@hawaii.edu>, Rod Gammon <gam...@hawaii.edu>
> writes:
>
> >Is there a function to check if a pointer is stale?
> >
>
> No, but the pointer should be set to nil by Delphi when you or Delphi frees the
> memory. As it sometimes does not do this, it is good programming practice to
> set the pointer to nil immediately after the memory has been freed.

I didn't know there were any situations where deallocating memory
_did_ set a pointer to nil automatically(???)



> Also, if you declare an object and there is a possibility of it not being used
> (and especially if the object is declared in a procedure / function), you

> should set it to nil soon after it it declared. When the object is declared,


> Delphi _should_ set it to nil - but it doesn't always do it.

Depends on what you mean by "should". It doesn't say that it _does_
do so anywhere.

What gets set to nil (or zero or whatever) is _fields_ of an
object - this includes fields which are opbject types. If you have

type TAClass = class
FHmm: TAnotherObjectType;
constructor Whatever
destructor Destroy
end;

then you can safely say FHmm.Free in TAClass.Destroy, because the
field FHmm _is_ inititalized to nil by the constructor.

This is not the same thing as a local variable in a procedure -
local variables are not intitialized to nil. (And it also has nothing
to do with whether FHmm.Free sets the pointer to nil - it's the
_constructor_ TAClass.Whatever that set FHmm:= nil.)

--
David Ullrich

sig.txt not found

Hallvard Vassbotn

unread,
Feb 18, 1998, 3:00:00 AM2/18/98
to

On Tue, 17 Feb 1998 12:14:24 GMT, dmur...@pair.com (Duncan Murdoch)
wrote:

>In answer to the question about telling if a pointer is stale:
>there's no way to do it based on looking at the pointer, unless you
>use some programming convention that allows you to determine it.

Just for the fun of it, I've made some routines to check if a pointer
points to a valid object instance. This relies on some types and
routines from Ray Lischner's "Secrets of Delphi 2" (the S_VMT unit).

Note that this code is D3 specific. Small changes are needed for
D1/D2.

uses
S_VMT;

function ValidPtr(P: pointer; Size: Cardinal): boolean;
begin
Result := not IsBadReadPtr(P, Size);
end;

function ValidObjType(Obj: TObject; ClassType: TClass): boolean;
begin
Result := Assigned(Obj) and
ValidPtr(Pointer(Obj), SizeOf(TObject)) and
ValidPtr(Pointer(Obj), ClassType.InstanceSize);
end;

type
PClass = ^TClass;

function ValidPShortString(S: PShortString): boolean;
begin
Result := ValidPtr(S, SizeOf(Byte)) and
ValidPtr(S, Ord(S^[0])) ;
end;

function ValidClassParent(ClassParent: PClass): boolean;
begin
if ClassParent = nil then
Result := true
else
if ValidPtr(ClassParent, SizeOf(ClassParent^)) then
Result := (ClassParent^ = nil) or ValidClassType(ClassParent^)
else
Result := false;
end;

function ValidClassType(ClassType: TClass): boolean;
var
Vmt: PVmt;
begin
Vmt := GetVmt(ClassType);
Result := ValidPtr(Vmt, SizeOf(Vmt^)) and
(Vmt^.SelfPtr = ClassType) and
ValidPShortString(Vmt^.ClassName) and
ValidClassParent(PClass(Vmt^.ClassParent)) ;
end;

function ValidObj(Obj: TObject): boolean;
begin
Result := Assigned(Obj) and
ValidPtr(PClass(Obj), SizeOf(TClass)) and
ValidClassType(Obj.ClassType) and
ValidPtr(Pointer(Obj), Obj.InstanceSize);
end;

This is probably not foolproof, but it should work in most instances.
It works by checking for valid pointers using the Win32 API
IsBadReadPtr, checking that the VMT-pointer for the given object is
valid.

Using this code is _not_ recommended as an alternative to setting
instance pointers to nil after freeing them.
--
Hallvard Vassbotn
Falcon R&D, Reuters Norge AS

Duncan Murdoch

unread,
Feb 18, 1998, 3:00:00 AM2/18/98
to

On Wed, 18 Feb 1998 09:12:13 GMT, hall...@falcon.no (Hallvard
Vassbotn) wrote:
>Just for the fun of it, I've made some routines to check if a pointer
>points to a valid object instance. This relies on some types and
>routines from Ray Lischner's "Secrets of Delphi 2" (the S_VMT unit).

...

>This is probably not foolproof, but it should work in most instances.
>It works by checking for valid pointers using the Win32 API
>IsBadReadPtr, checking that the VMT-pointer for the given object is
>valid.

It's a good idea to use routines like that for debugging purposes, but
they are definitely not foolproof. After you free a TGizmo, some
other code may allocate a TSomething, and just happen to use the same
address for the allocation. Then your pointer to the TGizmo will
point to the TSomething, but it will still be a stale pointer.

>Using this code is _not_ recommended as an alternative to setting
>instance pointers to nil after freeing them.

Nor is setting pointers to Nil recommended as an alternative to having
enough knowledge of the state of your program to know whether a
pointer is stale or not.

Think of Nil as another non-stale value, one that takes up no space
and for which Free works really quickly. Then follow the rule that
you *never* free a stale pointer. That's a much better approach than
relying on Delphi to correct your programming mistakes.

Duncan

Ray Lischner

unread,
Feb 18, 1998, 3:00:00 AM2/18/98
to

On Tue, 17 Feb 1998 14:02:04 -0600, David Ullrich
<ull...@math.okstate.edu> wrote:

>AlanGLLoyd wrote:
>>
>> In article <34E90C87...@hawaii.edu>, Rod Gammon <gam...@hawaii.edu>
>> writes:
>>
>> >Is there a function to check if a pointer is stale?
>> >
>>
>> No, but the pointer should be set to nil by Delphi when you or Delphi frees the
>> memory. As it sometimes does not do this, it is good programming practice to
>> set the pointer to nil immediately after the memory has been freed.
>
> I didn't know there were any situations where deallocating memory
>_did_ set a pointer to nil automatically(???)


When you free a component, and the component's name is the same as the
name of a published field in the component's owner, and that field
refers to the component, Delphi automatically sets the field to nil.

That sounds complicated and convoluted, but once you understand what
Delphi is doing, it makes sense.

When you drop a component on a form, Delphi automatically adds a
published field to the form's class declaration. When you set the name
of the component, Delphi always makes sure the field's name matches
the component's name.

When Delphi loads a DFM, it automatically creates the components
listed in the DFM. When a component's name matches a field's name,
Delphi sets the field to refer to the newly created component. That's
what lets you refer to the components on the form by name.

It doesn't happen often, but sometimes you must manually free a
component that was automatically created. When your program does so,
Delphi automatically sets the corresponding field to nil. This makes
sense because Delphi automatically set the field to the appropriate
object reference.

Some programmers are confused by the fact that Delphi seems to have
automatic memory management when it comes to forms and components, but
does not when it comes to any other object or dynamic memory
reference. The truth is that Delphi does not have any automatic memory
management, but it plays some fancy tricks in the VCL to make our
everyday jobs easier.
--
Ray Lischner (http://www.tempest-sw.com/)
Author of "Hidden Paths of Delphi 3: Experts, Wizards, and the Open Tools API"

Sundial Services

unread,
Feb 18, 1998, 3:00:00 AM2/18/98
to

In article <34edd968...@news.ccs.queensu.ca> dmur...@pair.com (Duncan Murdoch) writes:

>>Using this code is _not_ recommended as an alternative to setting
>>instance pointers to nil after freeing them.

>Nor is setting pointers to Nil recommended as an alternative to having
>enough knowledge of the state of your program to know whether a
>pointer is stale or not.

>Think of Nil as another non-stale value, one that takes up no space
>and for which Free works really quickly. Then follow the rule that
>you *never* free a stale pointer. That's a much better approach than
>relying on Delphi to correct your programming mistakes.


The point we are all saying is that you, the programmer, need to be absolutely
certain at all times that a pointer or an object-reference is EITHER nil OR
known to be a valid pointer to an existing object. The amount of CPU time
required to do this is truly negligible (read: one instruction).

If you are writing a routine that manages various things for clients, e.g. a
DLL that obliges the user to pass a "handle" back and forth, I also strongly
recommend that you validate that handle in each and every function that
receives one. You actually look up the value .. hashing is handy here .. to
make sure that it does in fact refer to an object you are cacheing, and if
possible, that it does in fact belong to the caller who is providing it.

The amount of time required to do this validation is measured in milliseconds
and costs nothing. The amount of time required to trap and debug a random,
catastrophic failure caused by a bogus handle is measured in days or weeks and
costs thousands of dollars.


Dave Shapiro

unread,
Feb 18, 1998, 3:00:00 AM2/18/98
to

(* Couldn't find the attribution for this. Someone else deleted it. *)

Someone wrote:

> I didn't know there were any situations where deallocating memory
> _did_ set a pointer to nil automatically(???)

In D2 and D3, ReallocMem sets a Pointer to nil if it is assigned and
you are Reallocing it to 0. To wit:

var
P: Pointer;

begin
{ Allocate some space with ReallocMem. Make sure P is nil first. }
P := nil;
ReallocMem(P, 561);

{ Equivalent code with GetMem. }
GetMem(P, 561);

{ Deallocate the space with ReallocMem. P is set to nil for you. }
ReallocMem(P, 0);

{ Equivalent code with FreeMem. }
FreeMem(P);
P := nil;
end;

Using ReallocMem instead of GetMem is far safer, because ReallocMem
won't mess with a nil Pointer.

Dave

Hallvard Vassbotn

unread,
Feb 19, 1998, 3:00:00 AM2/19/98
to

On Wed, 18 Feb 1998 12:59:25 GMT, dmur...@pair.com (Duncan Murdoch)
wrote:

>On Wed, 18 Feb 1998 09:12:13 GMT, hall...@falcon.no (Hallvard


>Vassbotn) wrote:
>>Just for the fun of it, I've made some routines to check if a pointer
>>points to a valid object instance.
>

>It's a good idea to use routines like that for debugging purposes, but
>they are definitely not foolproof. After you free a TGizmo, some
>other code may allocate a TSomething, and just happen to use the same
>address for the allocation. Then your pointer to the TGizmo will
>point to the TSomething, but it will still be a stale pointer.

True.

>>Using this code is _not_ recommended as an alternative to setting
>>instance pointers to nil after freeing them.
>
>Nor is setting pointers to Nil recommended as an alternative to having
>enough knowledge of the state of your program to know whether a
>pointer is stale or not.
>
>Think of Nil as another non-stale value, one that takes up no space
>and for which Free works really quickly. Then follow the rule that
>you *never* free a stale pointer. That's a much better approach than
>relying on Delphi to correct your programming mistakes.

I tend to disagree a bit with you here. Depending on how complex and
dynamic your application is, to do what you suggest you would have to
keep a separate flag for each and every pointer in the program to
indicate whether the corresponding pointer is stale or not. It is just
convenient to use the storage space for the pointer itself for this
flag value.

If your design allows for more than one pointer to the same object,
you must implement some kind of reference counting or notification
system to keep all the pointers in sync.

Simple everyday example that violates your rule:

constructor TMyObject.Create;
begin
inherited Create;
FList := TList.Create;
A := 0;
B := C div A; // Div by Zero exception, FStrings will still be nil
when destructor is called
FStrings := TStringList.Create;
end;

destructor TMyObject.Destroy;
begin
FList.Free;
FStrings.Free;
inherited Destroy;
end;

In this destructor I free both objects without knowing if they are
stale (i.e. nil) or not. That violates your rule. But doing it any
otherway is impractical and almost impossible.

Duncan Murdoch

unread,
Feb 19, 1998, 3:00:00 AM2/19/98
to

On Thu, 19 Feb 1998 08:57:08 GMT, hall...@falcon.no (Hallvard
Vassbotn) wrote:

>On Wed, 18 Feb 1998 12:59:25 GMT, dmur...@pair.com (Duncan Murdoch)
>wrote:

>>Think of Nil as another non-stale value, one that takes up no space
>>and for which Free works really quickly. Then follow the rule that
>>you *never* free a stale pointer. That's a much better approach than
>>relying on Delphi to correct your programming mistakes.
>
>I tend to disagree a bit with you here

....


>Simple everyday example that violates your rule:

...


>In this destructor I free both objects without knowing if they are
>stale (i.e. nil) or not. That violates your rule. But doing it any
>otherway is impractical and almost impossible.

I think you misunderstood me: I'm saying that knowing a pointer is
Nil is as good as knowing that it's assigned, i.e. a pointer known to
be Nil or assigned is *not* a stale pointer.

All that I'm saying is that you have to design your program so that
you are never unsure about whether a pointer can be Free'd or not.
Setting it to Nil after you Free it is *not* enough to ensure this.
As you mentioned in a part I deleted, you sometimes have multiple
pointers to an object, and you need to worry about all of them.

Duncan Murdoch

Hallvard Vassbotn

unread,
Feb 20, 1998, 3:00:00 AM2/20/98
to

On Thu, 19 Feb 1998 12:28:42 GMT, dmur...@pair.com (Duncan Murdoch)
wrote:

>I think you misunderstood me:

Yes, I probably did.

>All that I'm saying is that you have to design your program so that
>you are never unsure about whether a pointer can be Free'd or not.
>Setting it to Nil after you Free it is *not* enough to ensure this.
>As you mentioned in a part I deleted, you sometimes have multiple
>pointers to an object, and you need to worry about all of them.

Agreed. Your previous post led me to believe that you felt setting
pointers to nil after freeing was a bad thing.

In a prvious posting Duncan wrote:
>>Nor is setting pointers to Nil recommended as an alternative to having
>>enough knowledge of the state of your program to know whether a
>>pointer is stale or not.

Now we agree: Setting pointers and object references to nil after
freeing them _is_ recommended, but in addition you should have enough
knowledge and designed your program so that multiple references to the
same object have been taken into consideration (with reference
counting, notification system or what have you).

Erik Sperling Johansen

unread,
Feb 20, 1998, 3:00:00 AM2/20/98
to


David Ullrich wrote:

> I didn't know there were any situations where deallocating memory
> _did_ set a pointer to nil automatically(???)

I prefer to write my constructors/destructors like this. Assuming I have a FSomething
: POINTER field.

constructor...
do something which might cause an exception
GetMem (FSomething, SomeNumber)
do some more

destructor...
ReallocMem(FSomething, 0)
inherited

reallocmem will not fail if FSomething is nil, and it will change FSomething to nil
when done.

At least this saves a line of code...


Regards,

Erik.

--
Development of applications and drivers for Windows 95 and NT.
Go visit http://www.POBoxes.com/Sperling for some free source!
Check out Delphi Bug Lists at http://www.POBoxes.com/DelphiBugList
PGP public key available at http://www.POBoxes.com/Sperling/pgpkey.txt

Erik Sperling Johansen, Sper...@POBoxes.com (DeBug Team; checker, monitor)

David Ullrich

unread,
Feb 20, 1998, 3:00:00 AM2/20/98
to

Erik Sperling Johansen wrote:
>
> David Ullrich wrote:
>
> > I didn't know there were any situations where deallocating memory
> > _did_ set a pointer to nil automatically(???)
>
> I prefer to write my constructors/destructors like this. Assuming I have a FSomething
> : POINTER field.
>
> constructor...
> do something which might cause an exception
> GetMem (FSomething, SomeNumber)
> do some more
>
> destructor...
> ReallocMem(FSomething, 0)
> inherited
>
> reallocmem will not fail if FSomething is nil, and it will change FSomething to nil
> when done.
>
> At least this saves a line of code...

Not sure what this has to do with what I asked about. Anyway:
Does FreeMem fail if the pointer is nil? I didn't think so...
Of course FreeMem(FSomething, SomeNumber) could be a bad idea if FSomething
is nil, but I thought a simple FreeMem(FSomething) would be OK. (???)

Erik Sperling Johansen

unread,
Feb 21, 1998, 3:00:00 AM2/21/98
to


David Ullrich wrote:

> Not sure what this has to do with what I asked about. Anyway:

Nothing at all ;)

> Does FreeMem fail if the pointer is nil? I didn't think so...
> Of course FreeMem(FSomething, SomeNumber) could be a bad idea if FSomething
> is nil, but I thought a simple FreeMem(FSomething) would be OK. (???)

It is. I'm just confused, I've been working to much directly with SysFreeMem...
FreeMem(nil) is OK, SysFreeMem(nil) is not...

Reply all
Reply to author
Forward
0 new messages