Erreur Absraite [Résolu]

Messages postés
18
Date d'inscription
vendredi 8 avril 2005
Dernière intervention
7 avril 2007
- - Dernière réponse : f0xi
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
- 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;


labelo := Tlabel.Create(form2);
labelo.Parent := Form2;
labelo.Top := 40+(NbrPoints*25);
labelo.Caption := 'test';
labelo.Tag := 17;


Button := TButton.Create(Form2);
Button.Parent := Form2;
Button.Top := 60+(NbrPoints*25);
Button.OnClick := Form2.Enregistrer;
Button.Caption := 'Enregistrer';


SetLength(Edit,NbrPoints);
SetLength(EditDist,NbrPoints);
SetLength(TabloPoint,NbrPoints+1);




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;


for i := 0 to (NbrPoints -1) do
  begin


      EditDist[i] := TEdit.create(form2);
      EditDist[i].Parent := GB;
      EditDist[i].Name := 'Dist'+IntToStr(i);
      EditDist[i].Text := '0';
      EditDist[i].top := 20+(i*25);
      EditDist[i].Width := 60;
      EditDist[i].Left := 80;
  end;


 


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;
Afficher la suite 

Votre réponse

6 réponses

Meilleure réponse
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
3
Merci
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

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

  fKeyMask   := fKeyMask + ['0'..'9'];               // valeur numerique
  //fKeyMask   := fKeyMask + ['-'];                    // valeur numerique negative
  //fKeyMask   := fKeyMask + ['a'..'f','A'..'F','$'];  // valeur hexadecimale
  //fKeyMask   := fKeyMask + [DecimalSeparator];       // valeur a virgule

  // 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.

  if not (Key in fKeyMask) then
     Key := #0;
end;

end.






Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 106 internautes ce mois-ci

Commenter la réponse de f0xi
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Dernière intervention
19 novembre 2018
0
Merci
Je n'ai pas delphi sous la main, mais si tu remplaces le "form2.close" par "form2.hide", est-ce que ca fonctionne ?
Commenter la réponse de cptpingu
Messages postés
18
Date d'inscription
vendredi 8 avril 2005
Dernière intervention
7 avril 2007
0
Merci
Non, ça change rien, toujours cette erreur abstraite! pour le coup c'est vraiment abstrait!!!
Commenter la réponse de cs_OhAime
Messages postés
18
Date d'inscription
vendredi 8 avril 2005
Dernière intervention
7 avril 2007
0
Merci
J'ai essayé de le retourné dans tous les sens, et rien n'y fait  . Comment est-ce possible
Commenter la réponse de cs_OhAime
Messages postés
18
Date d'inscription
vendredi 8 avril 2005
Dernière intervention
7 avril 2007
0
Merci
ç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!

Merci beaucoup en tout cas! et à CptPingu aussi!
Commenter la réponse de cs_OhAime
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
0
Merci
rien que le fait de liberer le boutton alors que la methode est utilisée...

le fait aussi de ne pas assigner correctement parent/owner, peu provoquer des erreurs...

et le fait d'utiliser les mauvais evenement pour creer/liberer les object (onactivate par exemple).

Commenter la réponse de f0xi

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.