cs_OhAime
Messages postés18Date d'inscriptionvendredi 8 avril 2005StatutMembreDernière intervention 7 avril 2007
-
6 avril 2007 à 20:56
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 2022
-
7 avril 2007 à 15:00
Bonjour!
Alors voilà, une chose étonnante se passe! Je fait un petit programme qui necessite a un moment la création de composants dynamique. Jusque là ça va bien! ils sont créé sans probleme. Il y a une procedure dans la fiche contenant les composants dynamique, qui va sauvegarder les données rentrées dans ces composants.
Le problème c'est que la première fois ça fonctionne toujours, et souvent la deuxiemme fois j'ai le droit à: "Erreur Abstraite." (l'erreur arrivant à la fin de l'execution des opérations, le programme fonctionne quand même). Le plus bizarre c'est que cette erreur peut arriver comme elle peut ne pas arriver. Et pour couronner le tout, de temps en temps j'ai des erreur de violation d'accès...
Si vous avez une petite idée...
Merci d'avance.
code (en rouge, la localisation de l'erreur abstraite en mode pas à pas):
procedure TForm2.FormActivate(Sender: TObject);
var
i : integer;
begin
GB := TGroupBox.Create(Form2);
GB.Parent := Form2;
GB.Height := 25+(NbrPoints*25);
GB.Caption := 'test';
GB.Left := 40;
for i := 0 to (NbrPoints -1) do { je rempli deux tableau de TEdit dans la même boucle }
begin
Edit[i] := TEdit.Create(form2);
Edit[i].Parent := GB;
Edit[i].Name := 'PT'+IntToStr(i);
Edit[i].Top := 20+(i*25);
Edit[i].Width := 60;
Edit[i].Left := 10;
end;
procedure Tform2.Enregistrer(Sender: TObject);
var
i : integer;
begin
FichierINI2 := Tinifile.create(ExtractFilePath(Application.ExeName)+'\point.ini');
for i:= 0 to (NbrPoints - 1) do
begin
FichierINI2.WriteString(IntToStr(i),'distance',EditDist[i].text);
end;
form2.close;
end; <---- { erreur abstraite }
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
var
i : integer;
begin
for i: = 0 to (NbrPoints -1) do
begin
Edit[i].free;
EditDist[i].free;
end;
SetLength(Edit,0);
SetLength(EditDist,0);
GB.Free;
labelo.Free;
Button.Free;
form1.Visible := true;
end;
type
TForm2 = class(TForm)
private
// Penser a nomer correctement les composants
// toujours preparer des procedures d'aide
// respecter les conventions d'identification
fKeyMask : set of char;
fGpBox : TGroupBox;
fLabelo : TLabel;
fBtnSave : TButton;
fEditPnts : array of TEdit;
fEditDist : array of TEdit;
fNbrPoints: integer;
procedure EnterForm;
procedure ExitForm;
procedure DoSaveClick(Sender: TObject);
procedure DoNumericKeyPress(Sender : TObject; var Key : char);
public
// methode d'appel et d'affichage de la fiche (ShowModal nous donne que des avantages ici)
function Execute(const NbrPoints : integer) : boolean;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
uses IniFiles;
function TForm2.Execute(const NbrPoints : integer) : boolean;
begin
// preparation du masque de saisie pour les boites de saisie.
fKeyMask := []; // init.
fKeyMask := fKeyMask + #08; // obligatoire
// definition du nombre de points
fNbrPoints := NbrPoints;
// passage au premier plan
BringToFront;
// appel preventif de la routine qui detruit les composants (prevention des fuites memoire)
ExitForm;
// appel de la routine qui crée les composants
EnterForm;
// attente d'une action de sortie (mrOK) result :ShowModal mrOk;
// appel de la routine qui detruit les composants
ExitForm;
end;
procedure TForm2.EnterForm;
var
i : integer;
begin
// attention, il ne faut jamais appeler la variable FormX dans l'implementation
// d'une classe TFormX. il faut appeler SELF.
// Le parent doit toujours etre le Owner (sauf cas exceptionnels ne concernant pas
// les debutants).
fGpBox := TGroupBox.Create(Self);
with fGpBox do
begin
Parent := Self;
Name := 'fGpBox';
Caption := 'test';
Height := 25+(fNbrPoints*25);
Left := 40;
end;
fLabelo := Tlabel.Create(Self);
with fLabelo do
begin
Parent := Self;
Name := 'fLabelo';
Caption := 'test';
Top := 40+(fNbrPoints*25);
Tag := 17;
end;
fBtnSave := TButton.Create(self);
with fBtnSave do
begin
Parent := self;
Name := 'fBtnSave';
Top := 60+(fNbrPoints*25);
OnClick := Self.DoSaveClick;
ModalResult := mrOk;
Caption := 'Enregistrer';
end;
// pour les boucles on ne se base pas sur fNbrPoints mais sur la profondeur
// réelle du tableau d'objet.
SetLength(fEditPnts, fNbrPoints);
for i := 0 to High(fEditPnts) do
begin
fEditPnts[i] := TEdit.Create(fGpBox);
with fEditPnts[i] do
begin
Parent := fGpBox;
// OnKeyPress := DoNumericKeyPress;
Name := 'EdtPnt'+IntToStr(i);
Text := '';
Width := 60;
Top := 20+(i*25);
Left := 10;
end;
end;
SetLength(fEditDist, fNbrPoints);
for i := 0 to High(fEditDist) do
begin
fEditDist[i] := TEdit.create(fGpBox);
with fEditDist[i] do
begin
Parent := fGpBox;
OnKeyPress := DoNumericKeyPress;
Name := 'EdtDst'+IntToStr(i);
Text := '0';
Width := 60;
Top := 20+(i*25);
Left := 80;
end;
end;
SetLength(TabloPoint, fNbrPoints+1);
end;
procedure TForm2.ExitForm;
var
i : integer;
begin
// on verifie que tout les objets sont assigné avant liberation
// cela est plus sur meme si ça n'empeche pas certaines erreur de programmation
// la liberation doit etre faite en inversion de la creation
// dernier créé = premier libéré.
// cela est bon pour eviter les erreurs de liberation et bon aussi
// pour les performances generale.
// on utilise le couple Assigned / FreeAndNil pour etre sur que notre reference d'objet ne
// conserveras pas une reference erronnée.
for i := high(fEditDist)downto 0 do
if Assigned(fEditDist[i]) then
FreeAndNil(fEditDist[i]);
SetLength(fEditDist, 0);
for i := High(fEditPnts)downto 0 do
if Assigned(fEditPnts[i]) then
FreeAndNil(fEditPnts[i]);
SetLength(fEditPnts, 0);
SetLength(TabloPoint, 0);
if Assigned(fGpBox) then
FreeAndNil(fGpBox);
if Assigned(fLabelo) then
FreeAndNil(flabelo);
if Assigned(fBtnSave) then
FreeAndNil(fBtnSave);
end;
procedure TForm2.DoSaveClick(Sender: TObject);
var
i : integer;
begin
// ici pas besoin d'objet intermediaire, on peu creer et utiliser directement
// ce genre d'objet (TFileStream, TIniFile, TRegistry)
// on utilise un bloc Try Finally pour prevenir des erreur de convertion
// de IntToStr ou d'erreur d'accés a fEditDist[x]
with Tinifile.create(ExtractFilePath(ParamStr(0))+'\point.ini') do
try
for i := 0 to High(fEditDist) do
WriteString(IntToStr(i), 'distance', fEditDist[i].text);
finally
Free;
end;
// en ayant definit le ModalResult du boutton sur mrOK celui ci a transmit un
// message modalresult a la fiche qui vas alors se repondre toute seule a ce
// message. plus besoin d'appeler la fermeture de la fiche ici et donc
// on libere cette methode ce qui eviteras de provoquer une violation d'accés
// lors de la liberation de BtnSave.
end;
procedure TForm2.DoNumericKeyPress(Sender : TObject; var Key : char);
begin
// ici on s'assure que les saisie correspondent a des valeurs
// definie par fKeyMask.
cs_OhAime
Messages postés18Date d'inscriptionvendredi 8 avril 2005StatutMembreDernière intervention 7 avril 2007 7 avril 2007 à 13:13
ça marche super! Je vais me pencher un peu plus sur quelques trucs que je ne comprends pas, mais merci beaucoup en tout cas, mais sinon concretement, qu'est-ce qui pouvait amener les erreurs abstraites? histoire que je comprenne un peu mieux ce genre d'erreur!