henryreynolds
asked on
Delphi Access violation : Seacrh list of TString objects
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
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.
Which line do you get the AV?
av on this line in the destroy (after you free, not necessary to set nil)
Fo_HeaderFields.Objects[iL oop] := nil;
and entry_id is always '0' !!!
test this:
fwiw, your indentation is very odd
Fo_HeaderFields.Objects[iL
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;
fwiw, your indentation is very odd
ASKER
in the function GetFieldNameHeader
imeediately if I dont find a match I get an av
imeediately if I dont find a match I get an av
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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;
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;
ASKER
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.Crea te;
Memo1.Lines.Add(oHeader.Ge tFieldName Header('RE PORT ID').FsHeader)
then I still get av
do you think I must you the if each time i seacrh ?
thank you very much for your help
it is just very frustrating with the AV
if I use this exactly
oHeader := Tafe_DataRecordHeader.Crea
Memo1.Lines.Add(oHeader.Ge
then I still get av
do you think I must you the if each time i seacrh ?
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
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
when you get an AV, hit Ctrl-C
and paste that to the forum
and paste that to the forum
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 :
instead :
other way to do it with exception management (there are many ways to do it, depending on what you do with the object)
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
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);
this is bad because in the case the header exist (which should be the most common case) you'll SEARCH TWICEinstead :
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);
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;
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;
hey ... that's my quote: "You didn''t add a "d" !, so i can''t find one !"
use your own ! :)
use your own ! :)
ASKER
Hi Geert_Gruwez
Everything is fine, thanx a lot for your help.
Everything is fine, thanx a lot for your help.
ASKER
thank you very much
I have most difficulties to see why the selected answer solves anything concerning access violation