| Autor |
Beitrag |
Jagg
      
Beiträge: 635
|
Verfasst: Sa 06.12.08 05:15
Hallo zusammen,
ich hoffe, bei Euch Hilfe zu finden :
Ich habe diesen Code, wo dynamische TRadiobuttons erstellt werden...
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; 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'; 2 : Dyn_MaskEdit.EditMask := '00,99;1;0'; end; end; 2 : Dyn_MaskEdit.EditMask := '0,99;1;0'; 3 : Dyn_MaskEdit.EditMask := '00,99;1;0'; 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 :
Delphi-Quelltext 1:
| var Dyn_Zusatz : array [1..20] of TRadioButton; |
...nun ist es so,das 6 TRadionbuttons erstellt werden
und dementsprechend werden diese auch wieder freigegeben :
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 :
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 Gausi: URL- durch Delphi-Tags ersetzt
|
|
Xentar
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: 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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 06.12.08 13:17
Erstens:
Wenn du die RadioButtons so erstellst, dann solltest du sie nicht selbst freigeben, das gibt dann Probleme:
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. 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:
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 
      
Beiträge: 635
|
Verfasst: 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
      
Beiträge: 2077
Erhaltene Danke: 2
Win XP
Delphi 5 Ent., Delphi 2007 Prof
|
Verfasst: 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 
      
Beiträge: 635
|
Verfasst: 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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 635
|
Verfasst: 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
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 08.12.08 15:48
Jagg hat folgendes geschrieben : | 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.
|
|
|