Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Delphi Access violation  : Seacrh list of TString objects

Posted on 2011-10-11
15
Medium Priority
?
317 Views
Last Modified: 2012-05-12
Good Day

I am having a problem where I am searching threw a list of string objects, if I dont find a match I get an access vioaltion, can someone please advice and show i am better way to search quicker if possible.

I have attached sample code
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  {Header Records}
  Tafe_DataFieldHeader = class(TObject)
  private
  public
    FsEntryId     : string;
    FsHeader      : string;
    FsDetail      : string;
    FsGetDetail   : string;
  end;

  Tafe_DataRecordHeader = class(TObject)
  private
    function AddFieldHeader(AEntryId, AHeader,ADetail,AGetDetail: string): integer;
    function ReadTheCount: integer;
  public
    Fo_HeaderFields: TStrings;
    constructor Create;
    destructor  Destroy; override;
    function    GetFieldHeader(AIndex: integer)   : Tafe_DataFieldHeader;
    function    GetFieldNameHeader(IName : STring): Tafe_DataFieldHeader;
    property    Count: integer  read ReadTheCount;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var oHeader     : Tafe_DataRecordHeader;
begin
   oHeader     := Tafe_DataRecordHeader.Create;
   Memo1.Lines.Add(oHeader.GetFieldNameHeader('d').FsHeader)
end;


{ Tafe_DataRecordHeader }

function Tafe_DataRecordHeader.AddFieldHeader(AEntryId, AHeader, ADetail,
  AGetDetail: string): integer;
var
  oRecord:  Tafe_DataFieldHeader;
begin
  oRecord               := Tafe_DataFieldHeader.Create;
  oRecord.FsEntryId     := AEntryId;
  oRecord.FsHeader      := AHeader;
  oRecord.FsDetail      := ADetail;
  oRecord.FsGetDetail   := AGetDetail;
  Result                := Fo_HeaderFields.AddObject(AEntryId, oRecord);

end;

constructor Tafe_DataRecordHeader.Create;
begin
   Fo_HeaderFields := TStringList.Create;

   //        Entry Id   Header                          Detail                       GetDetail
   AddFieldHeader('0',  'REPORT ID:  12345',            ''                         ,'NO');
   AddFieldHeader('0',  'REPORTING FOR: 10001 AAAAA' ,  ''                         ,'NO');
   AddFieldHeader('0',  'REPORTING TO: 10001 AAAAA'  ,  ''                         ,'NO');
   AddFieldHeader('0',  'ENTITY: 10001 AAAA'         ,  ''                         ,'NO');
   AddFieldHeader('0',  'SETTLEMENT'                 ,  ''                         ,'NO');
   AddFieldHeader('0',  'FUNDS TRANSFER AMOUNT:'     ,  ''                         ,'NO');
   AddFieldHeader('0',  'REC VALUE',                    'TOTAL BBBB',              'YES');
   AddFieldHeader('0',  'REC VALUE',                    'TOTAL CCCC',              'YES');
end;

destructor Tafe_DataRecordHeader.Destroy;
var
  iLoop: Integer;
begin
  for iLoop := Fo_HeaderFields.Count - 1 downto 0 do
  begin
    Fo_HeaderFields.Objects[iLoop].Free;
    Fo_HeaderFields.Objects[iLoop] := nil;
  end;
  Fo_HeaderFields.Clear;
  FreeAndNil(Fo_HeaderFields);
  inherited;
end;

function Tafe_DataRecordHeader.GetFieldHeader(
  AIndex: integer): Tafe_DataFieldHeader;
begin
  Result := Tafe_DataFieldHeader(Fo_HeaderFields.Objects[AIndex]);
end;

function Tafe_DataRecordHeader.GetFieldNameHeader(
  IName: STring): Tafe_DataFieldHeader;
var I : Integer;
    lnString : Integer;
begin
  Result := nil;
  for I := 0 to Fo_HeaderFields.Count -1  do
  begin
     lnString := Length(Tafe_DataFieldHeader(Fo_HeaderFields.Objects[i]).FsHeader);

     if copy(trim(IName),1,lnstring) = Tafe_DataFieldHeader(Fo_HeaderFields.Objects[i]).FsHeader then
     begin
        //ShowMessage(Tafe_DataFieldStructure(Fo_Fields.Objects[i]).FsReport + ' - '+Tafe_DataFieldStructure(Fo_Fields.Objects[i]).FsGroup + ' - '+Tafe_DataFieldStructure(Fo_Fields.Objects[i]).FsDetail) ;
        Result := Tafe_DataFieldHeader(Fo_HeaderFields.Objects[I]);
        break;
     end;
  end;
end;

function Tafe_DataRecordHeader.ReadTheCount: integer;
begin
  Result := Fo_HeaderFields.Count;
end;



end.

Open in new window

0
Comment
Question by:henryreynolds
  • 7
  • 4
  • 3
  • +1
15 Comments
 
LVL 19

Expert Comment

by:MerijnB
ID: 36947288
Which line do you get the AV?
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947451
av on this line in the destroy (after you free, not necessary to set nil)
Fo_HeaderFields.Objects[iLoop] := nil;

and entry_id is always '0' !!!

test this:
 
procedure TForm1.Button1Click(Sender: TObject);
var oHeader: Tafe_DataRecordHeader;
begin
  oHeader := Tafe_DataRecordHeader.Create;
  if oHeader.GetFieldNameHeader('d') = nil 
    Memo1.Lines.Add('You didn''t add a "d" !, so i can''t find one !')
  else  
    Memo1.Lines.Add(oHeader.GetFieldNameHeader('d').FsHeader);
end;

Open in new window



fwiw, your indentation is very odd
0
 

Author Comment

by:henryreynolds
ID: 36947456
in the function GetFieldNameHeader

imeediately if I dont find a match I get an av
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 38

Accepted Solution

by:
Geert Gruwez earned 2000 total points
ID: 36947471
finding a fieldname is very odd too

function Tafe_DataRecordHeader.GetFieldNameHeader(
  IName: String): Tafe_DataFieldHeader;
var 
  I : Integer;
  field: Tafe_DataFieldHeader;
begin
  Result := nil;
  for I := 0 to Fo_HeaderFields.Count -1  do
  begin
    obj := Tafe_DataFieldHeader(Fo_HeaderFields.Objects[i]);
    if SameText(IName, obj.FSHeader) then 
    begin
      Result := obj;
      break;
    end;
  end;
end;

Open in new window

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947480
your sample for the header constructor is also very odd: you have mixed header and detail
 
constructor Tafe_DataRecordHeader.Create;
begin
  Fo_HeaderFields := TStringList.Create;

  //        Entry Id   Header                          Detail                       GetDetail
  AddFieldHeader('0', 'REPORT ID', '12345', 'NO');
  AddFieldHeader('0', 'REPORTING FOR', '10001 AAAAA', 'NO');
  AddFieldHeader('0', 'REPORTING TO', '10001 AAAAA', 'NO');
  AddFieldHeader('0', 'ENTITY', '10001 AAAA', 'NO');
  AddFieldHeader('0', 'SETTLEMENT', '', 'NO');
  AddFieldHeader('0', 'FUNDS TRANSFER AMOUNT', '', 'NO');
  AddFieldHeader('0', 'REC VALUE', 'TOTAL BBBB', 'YES');
  // AddFieldHeader('0', 'REC VALUE', 'TOTAL CCCC', 'YES'); >>>>> double header !!!!
end;

Open in new window

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947483
now try this code:
 
procedure TForm1.Button1Click(Sender: TObject);
var oHeader     : Tafe_DataRecordHeader;
begin
   oHeader     := Tafe_DataRecordHeader.Create;
   Memo1.Lines.Add(oHeader.GetFieldNameHeader('REPORT ID').FsHeader)
end;

Open in new window

0
 

Author Comment

by:henryreynolds
ID: 36947511
Hi Geert_Gruwez

thank you very much for your help

it is just very frustrating with the AV

if I use this exactly

oHeader     := Tafe_DataRecordHeader.Create;
   Memo1.Lines.Add(oHeader.GetFieldNameHeader('REPORT ID').FsHeader)

then I still get av

do you think I must you the if each time i seacrh ?
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947668
AV ...
for short: Access violation

please do not limit your information that much

when you go to a garage with your car, how do you think the mechanic will react when you say:"it's broken"
he will ask lots and lots of questions
to prevent that, please explain your problem in detail

like:
when my wife, me and the kids are all in the car and we start driving, the car makes screeching noises from the back left wheel
at least the mechanic would now have an idea of which part is broken

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947669
when you get an AV, hit Ctrl-C
and paste that to the forum
0
 
LVL 25

Expert Comment

by:epasquier
ID: 36947703
of course you get AV !
1) GetFieldNameHeader can return nil (if header not found), and pretty muchas it SHOULD be with GetFieldHeader if your index is <0 or >=Count - but in these cases you don't even check these conditions and get an Index out of bound exception

2) When you do receive nil, GetFieldNameHeader('REPORT ID').FsHeader will create the AV

so yes, you HAVE to test the returned header <> nil before accessing it's properties. OR you manage the exceptions - having an AV exception is not too bad, if you KNOW it is normal to have some here, and that you MANAGE them properly each time you use the code that can throw it.

If you want to test the header <> nil each time before using it, be smart : save it in a variable first, in order to avoid precisely the quick sample Geert gave you :
  if oHeader.GetFieldNameHeader('d') = nil 
    Memo1.Lines.Add('You didn''t add a "d" !, so i can''t find one !')
  else  
    Memo1.Lines.Add(oHeader.GetFieldNameHeader('d').FsHeader);

Open in new window

this is bad because in the case the header exist (which should be the most common case) you'll SEARCH TWICE
instead :

Var 
 TempHeader:Tafe_DataFieldHeader;
...
  TempHeader:=oHeader.GetFieldNameHeader('d')
  if TempHeader = nil 
    Memo1.Lines.Add('You didn''t add a "d" !, so i can''t find one !')
  else  
    Memo1.Lines.Add(TempHeader.FsHeader);

Open in new window


other way to do it with exception management (there are many ways to do it, depending on what you do with the object)
with oHeader.GetFieldNameHeader('d') do 
 try 
    Memo1.Lines.Add(TempHeader.FsHeader);
 except
    Memo1.Lines.Add('You didn''t add a "d" !, so i can''t find one !');
 end;

Open in new window

0
 
LVL 25

Expert Comment

by:epasquier
ID: 36947719
typo error on last sample code (Inside a With .. do I can/must use the field name directly. In my previous code I used the field of TempHeader variable - which I don't even use anymore in this sample
with oHeader.GetFieldNameHeader('d') do 
 try 
    Memo1.Lines.Add(FsHeader); // accessing Fsheader field of a 'nil' returned value will raise AV
 except
    Memo1.Lines.Add('You didn''t add a "d" !, so i can''t find one !');
 end;

Open in new window

0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 36947725
hey ... that's my quote: "You didn''t add a "d" !, so i can''t find one !"
use your own ! :)
0
 

Author Comment

by:henryreynolds
ID: 36947788
Hi Geert_Gruwez

Everything is fine, thanx a lot for your help.
0
 

Author Closing Comment

by:henryreynolds
ID: 36947791
thank you very much
0
 
LVL 25

Expert Comment

by:epasquier
ID: 36947990
I have most difficulties to see why the selected answer solves anything concerning access violation
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Integration Management Part 2
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses
Course of the Month11 days, 19 hours left to enroll

564 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