[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

Exception in ntdll.dll when clearing form

Posted on 2004-10-21
13
Medium Priority
?
1,231 Views
Last Modified: 2012-05-05
I am trying to free all objects on a form inside a DLL. I have written some code but get the following exception (I'm using XP Pro, not tested on other platforms).

Access Violation at address 7C918FEA in module 'ntdll.dll'. Write of address 00000010.

My code works after displaying this exception numerous times. Here is the code I have.

procedure TotalClearPage;
var
  i: Integer;
  o: TComponent;
begin
  try
    for i:=0 to Objects.Count-1 do
    begin
      o:=TheForm.Form.FindComponent(Objects.Strings[i]);
      if o<>nil then
      begin
        TheForm.Form.RemoveComponent(o);
        o.Free;
        o:=nil;
      end;
    end;
  finally
    Objects.Clear;
  end;
end;

Objects does contain a valid list of the components on the form.
0
Comment
Question by:paulb1989
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
  • +2
13 Comments
 
LVL 1

Expert Comment

by:sokpas
ID: 12374987
You should remove the components like this:

procedure TotalClearPage;
var
  i: Integer;
  o: TComponent;
begin
  try
    for i:=Objects.Count-1 downto 0 do  <=============== HERE IS THE RIGHT WAY
    begin
      o:=TheForm.Form.FindComponent(Objects.Strings[i]);
      if o<>nil then
      begin
        TheForm.Form.RemoveComponent(o);
        o.Free;
        o:=nil;
      end;
    end;
  finally
    Objects.Clear;
  end;
end;
0
 
LVL 17

Expert Comment

by:geobul
ID: 12378617
Hi,

I'm not sure I understand why you need such code and where you're calling that routine. You are manually freeing components owned by a form and that same thing will de executed if you simply call  TheForm.Form.Release;

Regards, Geo
0
 
LVL 6

Expert Comment

by:vadim_ti
ID: 12378757
i do not see any problem with your code

only thing may be

TheForm
or
TheForm.Form

already not valid when you call your function
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12379428
@Sokpas, it doesn't matter in which order he is freeing the components because he uses his own object list to store just the names of the component to delete. He is not deleting any items from the list itself. He just uses the list to find components on the form and then frees those components.

However, I do think this is weird:

    for i:=0 to Objects.Count-1 do <<<<<<<<<<
    begin
      o:=TheForm.Form.FindComponent(Objects.Strings[i]); <<<<<<<<<<

Apparantly, Objects has a stringlist connected to itself so I would have expected Objects.Strings.Count to be used instead of Objects.Count. But okay, this might be handled by the code correctly. (But it could cause problems if the count has an invalid value...)

@Geobul, I think he's just clearing the form of unnneeded components, not closing it...

@paulb1989, I think you should try stepping through this code and see which line actually causes the exception. Either turn "break on exception" on or put a breakpoint at the first "begin" of this procedure, then check what might be wrong here. And like vadim_ti I don't see anything in your code that is wrong, unless TheForm is not initialized correctly...
0
 
LVL 17

Accepted Solution

by:
geobul earned 500 total points
ID: 12379640
Try clearing the parent first:

      if o<>nil then
      begin
        o.Parent := nil;
        TheForm.Form.RemoveComponent(o);
        o.Free;
        // setting o to nil here is redundant I think
      end;

If all the components in Objects list have the form as a parent then the order of their freeing doesn't matter. But if you have a panel (parent = form) as number 3 in the list and a button (parent = the panel N3) having number 6 in the list later on then the order of freeing should be reversed, i.e.

for i:=Objects.Count-1 downto 0 do  

as sokpas already mentioned.

Regards, Geo
0
 
LVL 17

Expert Comment

by:geobul
ID: 12379677
Ops, I had OWNER in mind not parent when speaking about the order of freeing. Some components may have owner different than the form when created by code, you know.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12379786
Geo, it doesn't matter if he uses
  for i:=0 to Objects.Count-1 do
or
  for i:=Objects.Count-1 downto 0 do
since he NEVER seems to remove items from the list. He just removes components from his form where their names exist in this list... Don't act like a robot by providing default answers, please. ;-)

But maybe he should use:
  O.Owner.RemoveComponent(O);
instead. You need to remove them from their owner, not from the form. ;-)

Then again, I also wonder why you just can't free them directly. That should remove them from their owner too.
0
 
LVL 17

Expert Comment

by:geobul
ID: 12380028
Alex, at first I thought that it does matter if the owner of a component has already been freed when you get to that component in the list. Again, for instance, on the loop 3 you are freeing a panel which owns other components listed later in Objects. When you reach these components and try to free them you'll get an AV because PanelX.Free has also freed them already. But in this case FindComponent won't find them, so you are right :-)
0
 
LVL 17

Expert Comment

by:geobul
ID: 12380147
BTW, I think that
O.Owner.RemoveComponent(O);
is the same as
TheForm.Form.RemoveComponent(o);
in that case because FindComponent returns components owned by the form only.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12380944
Of course I'm right! ;-) I knew it couldn't find a component when it's owner has been freed, thus it works quite nice. :-)
But if these components are created without any owner being assigned to them...?
0
 
LVL 5

Author Comment

by:paulb1989
ID: 12381875
Thanks all for trying, but geobuls worked, but I had to check if the component was a control then typecast it to get the parent property. Then it worked fine.

if o is TControl then
  TControl(o).Parent:=nil;

Objects didnt just have a stringlist inside it, but is a TStringList.

All components had their owner as TheForm.Form, so freeing backwards didnt matter. Its TheForm.Form because I am using the SUIPack skinning components and Form is my TSUIForm on which all components are placed.

I couldnt free them directly, as I dont know their names at design time, they are created at runtime.

This may seem like a strange thing to be doing at runtime, but its because I'm making a Multimedia Authoring tool that is based on pages, so when I load a new page I have to clear the current one first, or both pages objects would be shown.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12414207
Oh, I see... You're not using Objects[i] but the longer version Objects.Strings[i]... Well, okay... My mistake. ;-)

But if you have to check if it's a control then it seems your list is "contaminated" with names of items that are not controls. Maybe you should do it easier and use FindChildControl instead... Same syntax, but it returns controls, not components. Saves you a little typecasting. ;-)

(Advise free of charge, btw.)
0
 
LVL 5

Author Comment

by:paulb1989
ID: 12414296
Some of the names in the list are TComponents and not TControls, so I still need to free these. There are also some components on the form that I have to leave there, so I can't use FindChildControl either.

The Object list is working fine now anyway, thanks :)
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …
Suggested Courses

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question