Autor Beitrag
Jagg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 635



BeitragVerfasst: Sa 06.12.08 05:15 
Hallo zusammen,

ich hoffe, bei Euch Hilfe zu finden :
Ich habe diesen Code, wo dynamische TRadiobuttons erstellt werden...
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
procedure TfmDynArt.FormShow(Sender: TObject);
 var iLauf_FormProp : integer;
begin
  Label_artnrWert.Caption        := ArtNr;
  Label_BezeichnungWert.Caption  := NameCopy+'...';
  fmDynArt.Caption               := ' Artikel-Zusatz (ESC = Abbruch)';
  Label_BezeichnungWert.Width    := Length(NameCopy)*8-15;
  //fmDynArt.Width                 := Length(Label_bezeichnung.Caption+NameCopy)*8;
  iDyn_Zusatz                    := 1;
  iDynLauf_Top                   := 25;
  iDynLauf_ZusatzEND             := 0;
  fmMain.Table_speisenGetraenke.First;
  while not fmMain.Table_speisenGetraenke.Eof do
  begin
    if pos(ArtNr+',',fmMain.Table_speisenGetraenke.FieldByName('Name').AsString)<>0 then
    begin
      Pos_3Striche  := pos('---',fmMain.Table_speisenGetraenke.FieldByName('Name').AsString);
      Dyn_Zusatz[iDyn_Zusatz]            := TRadioButton.Create(fmDynArt);
      Dyn_Zusatz[iDyn_Zusatz].Parent     := fmDynArt;
      Dyn_Zusatz[iDyn_Zusatz].Left       := Label_BezeichnungWert.Left;
      Dyn_Zusatz[iDyn_Zusatz].Top        := Label_BezeichnungWert.Top+iDynLauf_Top;
      Dyn_Zusatz[iDyn_Zusatz].Font.Name  := 'Tahoma';
      Dyn_Zusatz[iDyn_Zusatz].Font.Size  := 10;
      Dyn_Zusatz[iDyn_Zusatz].Font.Style := [fsbold];
      Dyn_Zusatz[iDyn_Zusatz].OnKeyPress := Dyn_Zusatz_KeyPress;
      RadioButtonTextNEU := Copy(fmMain.Table_speisenGetraenke.FieldByName('Name').AsString,1,Pos_3Striche-1);
      Pos_ArtZusatz := pos(';',fmMain.Table_speisenGetraenke.FieldByName('Name').AsString);
      Pos_Komma := pos(',',fmMain.Table_speisenGetraenke.FieldByName('Preis').AsString);
      case Pos_Komma of
        0 : begin
              case Length(fmMain.Table_speisenGetraenke.FieldByName('Preis').AsString) of
                1 : Dyn_MaskEdit.EditMask := '0,99;1;0';   // Wenn Länge Einzelpreis = 1, z.b. 7  €...ArtNr : 36
                2 : Dyn_MaskEdit.EditMask := '00,99;1;0';  // Wenn Länge Einzelpreis = 2, z.b. 13 €...ArtNr : 23
              end;
            end;
        2 : Dyn_MaskEdit.EditMask := '0,99;1;0';  // Wenn Kommma an 2 Stelle, z.b. 7,5  €...ArtNr : 45
        3 : Dyn_MaskEdit.EditMask := '00,99;1;0'// Wenn Kommma an 3 Stelle, z.b. 11,5 €...ArtNr : 47
      end;
      Dyn_MaskEdit.Text := fmMain.Table_speisenGetraenke.FieldByName('Preis').AsString;
      if ArtNr[1] <> 'm' then
        Dyn_Zusatz[iDyn_Zusatz].Caption := Copy(RadioButtonTextNEU,Pos_ArtZusatz+1,Length(RadioButtonTextNEU))+
                                           '('+Dyn_MaskEdit.EditText+' €'+')'
      else
        Dyn_Zusatz[iDyn_Zusatz].Caption := Copy(RadioButtonTextNEU,Pos_ArtZusatz+1,Length(RadioButtonTextNEU));
      Dyn_Zusatz[iDyn_Zusatz].Width := Length(Dyn_Zusatz[iDyn_Zusatz].Caption)*8+15;
      inc(iDyn_Zusatz);
      inc(iDynLauf_ZusatzEND);
      iDynLauf_Top := iDynLauf_Top + 25;
      fmMain.Table_speisenGetraenke.Next;
    end
    else
      fmMain.Table_speisenGetraenke.Next;
  end;
  Dyn_Zusatz[1].Checked := True;


...zuvor habe ich die TRadiobutton so deklariert :
ausblenden Delphi-Quelltext
1:
var Dyn_Zusatz    : array [1..20of TRadioButton;					


...nun ist es so,das 6 TRadionbuttons erstellt werden
und dementsprechend werden diese auch wieder freigegeben :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TfmDynArt.FormClose(Sender: TObject; var Action: TCloseAction);
 var iDynLauf_ZusatzBEGIN : integer;
begin  
  for iDynLauf_ZusatzBEGIN := 1 to iDynLauf_ZusatzEND do
      Dyn_Zusatz[iDynLauf_ZusatzBEGIN].Free;
end;


... ich habe auch nachgeprüft, es werden WIRKLICH nur 6 TRadiobuttons erstellt und wieder freigegeben.
In diesem Fall werden nur 6 erstellt,weil abhängig von der Artikelnummer (ArtNr) es demzufolgend verschiedene Ausprägungen gibt.

NUN kommt der Code, wo ich vermute das der Fehler auftritt.
Es handelt sich hier bei um ein Ereignis KeyPress : Dyn_Zusatz[iDyn_Zusatz].OnKeyPress := Dyn_Zusatz_KeyPress;

...es wurde vorher so deklariert : type procedure Dyn_Zusatz_KeyPress(Sender: TObject; var Key: Char);

Code mit der Vermutung auf Fehler "Access Violation / Zugriffsverletzung :
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TfmDynArt.Dyn_Zusatz_KeyPress(Sender: TObject; var Key: Char);
begin
  if key = #13 then
  begin
    Pos_PreisBEGIN := pos('(',(Sender as TRadiobutton).Caption);
    Pos_PreisEND   := pos(')',(Sender as TRadiobutton).Caption);
    PreisCopy      := Copy((Sender as TRadiobutton).Caption,Pos_PreisBEGIN+1,Pos_PreisEND-1-Pos_PreisBEGIN);
    Pos_ZusatzEND  := pos('(',(Sender as TRadiobutton).Caption);
    ZusatzCopy     := Copy((Sender as TRadiobutton).Caption,1,Pos_ZusatzEND-1);
    fmMain.Stringgrid_artikel.Cells[1,fmMain.Stringgrid_artikel.RowCount-1] := NameCopy+ZusatzCopy;
    fmMain.Stringgrid_artikel.Cells[4,fmMain.Stringgrid_artikel.RowCount-1] := PreisCopy;
    fmDynArt.Close;
  end;
end;


...NUN erkläre Ich euch den Ablauf :
Wenn bei Eingabe der ArtNr, diese verschiedene Ausprägungen hat, erscheint ein neues Fenster, wo die dyn. TRadiobuttons aufgelistet werden.
Es wird eins markiert und bei Druck der Taste "Enter",wird der Name bzw. Daten des markierten Radiobutton in eine andere Form übernommen und diese Form mit den Radiobuttons closed sich dann.

Wenn Ich den Vorgang jetzt aber 3-4 mal durchführe erhalte Ich eine "Access Violation / Zugriffsverletzung".
Ich analysiere schon seit Tagen das Problem und ich weiss nicht mehr wo Ich noch suchen soll und deshalb wende Ich mich an euch.
Also, wie gesagt, ich vermute den Fehler an : procedure TfmDynArt.Dyn_Zusatz_KeyPress(Sender: TObject; var Key: Char);

...Was sagt Ihr dazu ?

Für Rückfragen stehe Ich euch natürlich zur Verfügung.

Jagg[meta]Test[/meta]

Moderiert von user profile iconGausi: URL- durch Delphi-Tags ersetzt
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Sa 06.12.08 05:33 
[URL] <-- Wat junge?!
URL steht für einen Link zu einer Internetseite, DELPHI für einen Code in gleichnamiger Programmiersprache. Also: Versuch's nochmal ;)

Hast du den Code mal im Compiler, also von Delphi aus ausgeführt? Der zeigt doch normalerweise direkt die Zeile an, wo der Fehler auftritt.

_________________
PROGRAMMER: A device for converting coffee into software.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 06.12.08 13:17 
Erstens:
Wenn du die RadioButtons so erstellst, dann solltest du sie nicht selbst freigeben, das gibt dann Probleme:
ausblenden Delphi-Quelltext
1:
Dyn_Zusatz[iDyn_Zusatz] := TRadioButton.Create(fmDynArt);					
So sagst du, dass du einen neuen RadioButton erstellen willst, um dessen Verwaltung (inkl. Freigabe) sind fmDynArt kümmern soll.

Wenn du die Verwaltung selber übernehmen willst, dann gib stattdessen nil an.
ausblenden Delphi-Quelltext
1:
Dyn_Zusatz[iDyn_Zusatz] := TRadioButton.Create(nil);					


Zweitens:
Die globalen Variablen machen den Code nicht gerade lesbarer...
Zum Beispiel wird NameCopy in Dyn_Zusatz_KeyPress nie zugewiesen, dann aber benutzt.

Drittens:
Es ist sehr schlechter Stil Daten als String in die RadioButtons zu legen und dann auszulesen. Speichere das doch lieber in einem zusätzlichen Array, zum Beispiel in Records. Dann wird dein Code sehr viel kürzer und übersichtlicher, weil du dir die ganzen Umwandel- und Stringoperationen sparst.
// EDIT:
Ach ja: Zur Identifikation des RadioButtons (um den Index im Array zu finden) kannst du die Eigenschaft Tag benutzen. In der kannst du bei jeder Komponente einen Integerwert speichern, den du frei verwenden kannst.

Viertens:
Dein (Sender as TRadiobutton).Caption:
as überprüft jedesmal ob die Umwandlung möglich ist. Besser ist es dies einmal mit is zu prüfen und danach immer direkt zu casten:
ausblenden Delphi-Quelltext
1:
2:
3:
if Sender is TRadioButton then
begin
  TRadiobutton(Sender).Caption...

Noch besser hier: speichere die Caption einmal am Anfang von Dyn_Zusatz_KeyPress in einen String und arbeite mit dem, sonst wird jedesmal der Typecast (bei dir mit as) und der Zugriff auf die EIgenschaft Caption gemacht. Das bremst deinen Code nur unnötig und macht ihn unübersichtlicher, weil jedesmal das lange (Sender as TRadiobutton).Caption statt einer kürzeren Variable benutzt wird.
Jagg Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 635



BeitragVerfasst: Sa 06.12.08 20:08 
@Xentar :
Wenn diese "Access Violation" Fehlermeldung auftritt, dann springt Delphi zu KEINER Zeile.
Es steht da nur diese Meldung !!!

@jaenicke :
Ich danke dir erstmal für die Verbessrungsvorschläge, ich werde diese dann auch beachten...aber anderseits, wie helfen Mir deine Verbesserungsvorschäge ?

Zu "Erstens" :
Zitat:
Erstens:
Wenn du die RadioButtons so erstellst, dann solltest du sie nicht selbst freigeben, das gibt dann Probleme.
1: Dyn_Zusatz[iDyn_Zusatz] := TRadioButton.Create(fmDynArt);

So sagst du, dass du einen neuen RadioButton erstellen willst, um dessen Verwaltung (inkl. Freigabe) sind fmDynArt kümmern soll.

Wenn du die Verwaltung selber übernehmen willst, dann gib stattdessen nil an.
1:Dyn_Zusatz[iDyn_Zusatz] := TRadioButton.Create(nil);


...ich habe das mit dem NIL ausprobiert, der Fehler tritt immer noch auf.

I NEED YOUR HELP !!!

Jagg
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Sa 06.12.08 20:23 
Schrei doch nicht so, wir sind doch nicht blind...

Dann anders:
Wenn die Access Violation auftritt, steht da normalerweise "EAccessViolation an Adresse 0x********", die merkst du dir, und gehst dann in Delphi Suchen -> Laufzeitfehler suchen (je nach Delphi Version auch "Zu Zeile springen"), und tippst dort die Adresse ein, dann sollte Delphi dir auch die Zeile anzeigen.

_________________
PROGRAMMER: A device for converting coffee into software.
Jagg Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 635



BeitragVerfasst: Sa 06.12.08 20:42 
Also, die Fehlermeldung lautet :

Zitat:
Zugrifssverletzung bei Adresse 00146737, Lesen von Adresse 0043181E


...Wenn Ich diese Adresse suche, kommt bei mir ein kleines CPU Fenster, wo viele Zahlen drinstehen, ich kann damit aber nix anfangen.

Ausserdem die Adressnummern sind immer unterschiedlich.

@Xentar : Ich korrigiere, es muss heissen : "Schrei nicht so, wir sind nicht TAUB" :)

Sorry, aber ich bin etwas genervt wegen der Sache.

Jagg
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 06.12.08 21:23 
Nun ja, wenn es schon beim 3.-4. Mal auftritt, dann wäre die einfachste Lösung wohl einfach ein Haltepunkt in dem KeyPress und dann Einzelschritt mit F7/F8 bis der Fehler auftritt.

Ansonsten bleibt nur überall wo es auftreten könnte Logeinträge beim Start und Ende der Prozeduren zu machen, so dass du dann feststellst wo der Fehler auftritt. Dabei kannst du die Datei ja jedesmal öffnen, die neue Zeile anhängen und die Datei wieder schließen, denn die Performance ist dabei ja egal.

Dann gibt es da noch Tools wie dieses, die dir die Zeilennummern von Fehlern ausgeben, sowas kann sich auch für das Ausliefern einer Software lohnen, auch wenn das dann bei kommerzieller Nutzung Geld kostet.
www.madshi.net/madExceptDescription.htm
Jagg Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 635



BeitragVerfasst: So 07.12.08 02:49 
Ich habe mal ne generelle Frage :

Wenn Ich KEIN TRadiobutton erzeuge, z.b Dyn_Zusatz[1].Create...aber es dann später trotzdem per FREE freigebe, erhalte ich dann eine Access Violation bzw. Zugriffverletzung ?

Jagg
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 07.12.08 02:58 
Das kann passieren, aber der Fall sollte bei einer sauberen Programmierung ja ohnehin nicht auftreten.

Generell überprüft Free vorher ob die Referenz nil ist, wenn aber ein anderer Wert als nil drin steht, das Objekt aber nicht gültig ist, zum Beispiel weil nicht FreeAndNil benutzt wurde um ein Objekt freizugeben, dann gibt es eine Zugriffsverletzung beim Aufruf von Free.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 08.12.08 15:48 
user profile iconJagg hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe mal ne generelle Frage :

Wenn Ich KEIN TRadiobutton erzeuge, z.b Dyn_Zusatz[1].Create...aber es dann später trotzdem per FREE freigebe, erhalte ich dann eine Access Violation bzw. Zugriffverletzung ?

Jagg

Darf ich Schmerzensgeld verlangen? Das tut einem ja richtig weh! Instanzvariable := Klassenname.Create(Parameter); ist die korrekte Variante

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.