1
votes

So here is my situation. I have a Form (MainMenu) and a Frame (TestFrame). TestFrame is displayed on a TPanel located on MainMenu. Using this code:

frTestFrame := TfrTestFrame.Create(nil);
frTestFrame.Parent := plMain;
frTestFrame.Align := alClient;
frTestFrame.Visible := true;

TestFrame displays fine with no error. TestFrame has a few TEdit boxes on it. A TButton on MainMenu calls a procedure located in TestFrame to check if the TEdit boxes text property is null.

procedure TfmMainMenu.tbCheckClick(Sender: TObject);
begin
frTestFrame.Check;
end;

This function on TestFrame is supposed to go through all the "TEdit" components and use the function GetErrorData that returns a string if the TEdit's text property is null. That string is added to a TStringList and displayed if any TEdit boxes are null.

function TfrTestFrame.Check: Boolean;
var
 ErrorList: TStringList;
 ErrorString: string;
 I: Integer;
begin
 ErrorList := TStringList.Create;
 for I := 0 to (frTestFrame.ComponentCount - 1) do
begin
  if (frTestFrame.Components[I] is TEdit) then
    begin
      ErrorString := GetErrorData(frTestFrame.Components[I]);
      if (ErrorString <> '') then
        begin
          ErrorList.Add(ErrorString);
        end;
    end;
end;
if (ErrorList.Count > 0) then
begin
  ShowMessage('Please Add The Following Information: ' + #13#10 + ErrorList.Text);
  result := false;
end;
result := true;
end;

function TfrTestFrame.GetErrorData(Sender: TObject): string;
var
 Editbox: TEdit;
 ErrorString: string;
begin
if (Sender is TEdit) then
 begin
   Editbox := TEdit(Sender);
   if (Editbox.Text <> '') then
     begin
       Editbox.Color := clWindow;
       result := '';
     end
   else
    begin
      Editbox.Color := clRed;
      ErrorString := Editbox.Hint;
      result := ErrorString;
    end;
end;
end;

The problem is that when it hits the line "for I := 0 to (frTestFrame.ComponentCount - 1) do " It blows up and I get the error "Access violation at 0x00458... Read of address 0x000..." I do not know why this error is happening. I can only assume that maybe the Frame is not getting creating. Any help would be great. Thanks in advance.

1
TfrTestFrame.Check() is leaking the TStringList.Remy Lebeau
Thanks Remy. I freed it at the end of the function.T.J.

1 Answers

3
votes

According to your question, the line

for I := 0 to (frTestFrame.ComponentCount - 1) do

leads to an access violation at address 0x000..... Now, for a start, why won't you tell us the precise error message with the full details? Hiding the address makes it harder!

Anyway, it looks like the address is going to be a value very close to zero. In any case the only explanation for an access violation there is that frTestFrame is invalid. Most likely it is nil.

I note that the code in question is inside a TfrTestFrame method. So why do you use frTestFrame to refer to the object? You are already inside an instance of the object. Do you have multiple global variables named frTestFrame? Perhaps one in the main form unit and one in the frame unit?

You should stop using global variables for your GUI objects. I know that the IDE leads you that way. Resist the temptation to program that way. Abuse of global variables leads to pain and suffering.

Since the code is inside a TfrTestFrame method you can use Self. In all your TfrTestFrame methods remove all references to frTestFrame. Your loop should be like this:

for I := 0 to ComponentCount - 1 do

and the rest of the methods in that class need similar treatment. Note that you don't need to explicitly write Self and it is idiomatic not to.

Finally, I urge you to learn how to use the debugger. It's a wonderful tool and if you would use it, it would have told you what the problem was. Don't be helpless, let the tools help you.