AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Funktionsaufruf innerhalb With..do => access violation
Thema durchsuchen
Ansicht
Themen-Optionen

Funktionsaufruf innerhalb With..do => access violation

Ein Thema von Hobbycoder · begonnen am 6. Mär 2017 · letzter Beitrag vom 6. Mär 2017
Antwort Antwort
Hobbycoder

Registriert seit: 22. Feb 2017
961 Beiträge
 
#1

Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 11:52
Hi,

ich hänge mal wieder an eine möglicherweise recht simplen Problem.
Ich erzeuge in meinem Programm einige Forms dynamisch. Zwecks Formatüberprüfung für z.B. eine Faxnummer nutze ich eine Function, die in einer separaten Unit liegt, in 2 dynamisch erzeugen Formularen jeweils im OnExit-Event eine JvValidateEdit um eine Faxnummer automatisch richtig zu formatieren. So weit kein Problem, läuft fehlerfrei.
Bei den beiden Formularen handelt es sich um eine Adressliste und eine Formular zur Adressenerfassung.

Wird jetzt beim Editieren einer Adresse das Formular zur Adressenerfassung erzeugt, möchte ich (im Falle eines des Editieren bereits vorhandener Daten) auch gleich eine Validierung der Faxnummer vornehmen. Der Aufruf ist identisch mit dem im OnExit-Event der Erfassungsform.
Jedoch kommt beim Aufruf der Function bereits eine AccessViolation. Ich habe Probleme mir das zu erklären. Objekte sind alle erzeugt, Uses ist auch passig, Compiler hat nix zu meckern und ich kann über den Debugger auch darauf zugreifen. Aber per Einzelschritt komme ich nicht einmal in die Funktion.

Hier mal der Code:
Delphi-Quellcode:
procedure Tfrm_Adressbuch.btn_aendernClick(Sender: TObject);
var
  LKZ, ONKZ, RN: string;
  idxLKZ, idxONKZ: Integer;
  faxnummer: string;
begin
  if lv_adressen.Selected=nil then Exit;
  with Tfrm_Adresse.Create(self) do
  begin
    try
      edt_name.Text:=Adressbuch[lv_adressen.Selected.Index].Name;
      edt_vorname.Text:=Adressbuch[lv_adressen.Selected.Index].Vorname;
      edt_firma.Text:=Adressbuch[lv_adressen.Selected.Index].Firma;
      faxnummer:=Adressbuch[lv_adressen.Selected.Index].Faxnummer;
      faxnummer:=ValidateNumber(faxnummer, CountryList, ONKZList, Settings.OwnCountryPrefix, Settings.OwnCityPrefix, LKZ, ONKZ, RN, idxLKZ, idxONKZ); // <-- Hier kommt die Access Violation
      edt_faxnummer.Text:=faxnummer;
      if idxLKZ>-1 then lbl_LKZ.Caption:=CountryList[idxLKZ].CountryDE;
      if idxONKZ>-1 then lbl_ONKZ.Caption:=ONKZList[idxONKZ].Ort;
      CountryList:=Self.CountryList;
      ONKZList:=Self.ONKZList;
      Settings:=Self.Settings;
      if ShowModal=mrOK then
      begin
        Adressbuch[lv_adressen.Selected.Index].Name:=edt_name.Text;
        Adressbuch[lv_adressen.Selected.Index].Vorname:=edt_vorname.Text;
        Adressbuch[lv_adressen.Selected.Index].Firma:=edt_firma.Text;
        Adressbuch[lv_adressen.Selected.Index].Faxnummer:=edt_faxnummer.Text;
        Adressbuch.SortByName;
        Adressbuch.SaveToFile(AdressenFilename);
        BuildLV;
      end;
    finally
      Free;
    end;
  end;
end;
Und die Function sieht folgendermaßen aus:
Delphi-Quellcode:
function ValidateNumber(Number: string; CountryList: TCountryList; ONKZList: TONKZList;
  OwnCountryPrefix: string; OwnCityPrefix: string;
  var LKZ, ONKZ, RN: string; var idxLKZ, idxONKZ: integer): string;
Wie gesagt in den OnExit-Events innerhalb des Tfrm_Adresse-Formular kann ich die Funktion problemlos aufrufen.

Hat irgendeiner eine Idee woran das liegen kann? Ist sicher mein Fehler, aber ich verstehe nicht warum.
Gruß Hobbycoder
  Mit Zitat antworten Zitat
Benutzerbild von rweinzierl
rweinzierl

Registriert seit: 22. Mär 2005
98 Beiträge
 
#2

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 12:02
Hallo

Niemals, wirklich niemals with verwenden, macht den Code nur schwer lesbar.

Weise deinem Formular eine Instanzvariable zu und lasse es nochmals durch den Debugger laufen.

Ohne with bekommst du auch im Debugger hints was in den Variablen drin steht.

Ändere deinen Code bitte ab und poste ihn dann nochmals, vielleicht findest du ihn so selber oder wir können dir besser helfen

mfg

Reinhold
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.800 Beiträge
 
Delphi 12 Athens
 
#3

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 12:07
Mehr gibts dazu zwar nicht zu sagen, aber der Vollständigkeit halber: With ist mindestens so schädlich wie Goto!

Sherlock
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
961 Beiträge
 
#4

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 12:08
Der Erfolg gibt die Recht. So funktioniert es.

Kannst du mir auch erklären warum?

Delphi-Quellcode:
procedure Tfrm_Adressbuch.btn_aendernClick(Sender: TObject);
var
  LKZ, ONKZ, RN: string;
  idxLKZ, idxONKZ: Integer;
  faxnummer: string;
  Adresse: Tfrm_Adresse;
begin
  if lv_adressen.Selected=nil then Exit;
  Adresse:=Tfrm_Adresse.Create(self);
  try
    Adresse.edt_name.Text:=Adressbuch[lv_adressen.Selected.Index].Name;
    Adresse.edt_vorname.Text:=Adressbuch[lv_adressen.Selected.Index].Vorname;
    Adresse.edt_firma.Text:=Adressbuch[lv_adressen.Selected.Index].Firma;
    faxnummer:=Adressbuch[lv_adressen.Selected.Index].Faxnummer;
    faxnummer:=ValidateNumber(faxnummer, CountryList, ONKZList, Settings.OwnCountryPrefix, Settings.OwnCityPrefix, LKZ, ONKZ, RN, idxLKZ, idxONKZ);
    Adresse.edt_faxnummer.Text:=faxnummer;
    if idxLKZ>-1 then Adresse.lbl_LKZ.Caption:=CountryList[idxLKZ].CountryDE;
    if idxONKZ>-1 then Adresse.lbl_ONKZ.Caption:=ONKZList[idxONKZ].Ort;
    CountryList:=Self.CountryList;
    ONKZList:=Self.ONKZList;
    Settings:=Self.Settings;
    if Adresse.ShowModal=mrOK then
    begin
      Adressbuch[lv_adressen.Selected.Index].Name:=Adresse.edt_name.Text;
      Adressbuch[lv_adressen.Selected.Index].Vorname:=Adresse.edt_vorname.Text;
      Adressbuch[lv_adressen.Selected.Index].Firma:=Adresse.edt_firma.Text;
      Adressbuch[lv_adressen.Selected.Index].Faxnummer:=Adresse.edt_faxnummer.Text;
      Adressbuch.SortByName;
      Adressbuch.SaveToFile(AdressenFilename);
      BuildLV;
    end;
  finally
    Adresse.Free;
  end;
end;
  Mit Zitat antworten Zitat
bra

Registriert seit: 20. Jan 2015
711 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#5

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 12:33
Vermutlich greift der bei irgendeinem der ValidateNumber-Parameter ins Leere. Man sieht halt bei dem With-Code nicht, woher die einzelnen Variablen kommen, aus Adresse oder aus Self. Darum möglichst With nicht verwenden.
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#6

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 12:39
Ohne den vollständigen Quelltext und die vollständige Formulardefinition wird das konkrete Erkennen der Fehlerursache schwierig. Mal ein einfaches Beispiel, um auf eine mögliche Fehlerursache hinzuweisen:

Gegeben sei ein Formular (Form1) mit 'nem Label (Label1) drauf:
Delphi-Quellcode:
with Form1 do begin
  Caption := Label1.Caption;
end;

with Form1 do begin
  with Label1 do begin
    Caption := Caption;
  end;
end;

with Form1, Label1 do begin
  Caption := Caption;
end;
Diese Beispiele sind extrem verkürzt, machen aber hoffentlich klar, dass auch bei korrekter Syntax und Kompilierbarkeit von Quelltext bei der Verwendung von With "Namenskonflikte" auftreten können.

D. H.: Es kann sein, dass bei mehreren gleichnamigen Eigenschaften unterschiedlicher Objekte zwar eine syntaktisch korrekte Interpretation möglich ist, aber nicht zwingend vom Compiler die konkret gemeinte Eigenschaft genutzt wird, sondern die von ihm "vermutete" Eigenschaft. Die kann aber zur Laufzeit zu einem Objekt gehören, dass (noch) nicht erstellt wurde und dies führt zu dem von Dir beschriebenen Fehler.

Sprich: Es wird auf was anderes zugegriffen, als Du beim Schreiben und Lesen des Quelltextes meinst.
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
961 Beiträge
 
#7

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 13:45
Alles klar

ich habs dann noch mal so probiert:
Delphi-Quellcode:
       faxnummer:=ValidateNumber(faxnummer, self.CountryList, self.ONKZList, self.Settings.OwnCountryPrefix, Self.Settings.OwnCityPrefix, LKZ, ONKZ, RN, idxLKZ, idxONKZ); // <-- Hier kommt die Access Violation
       edt_faxnummer.Text:=faxnummer;
       if idxLKZ>-1 then lbl_LKZ.Caption:=Self.CountryList[idxLKZ].CountryDE;
       if idxONKZ>-1 then lbl_ONKZ.Caption:=Self.ONKZList[idxONKZ].Ort;
Und nun eindeutigen Referenz mittels self greift er nun auf die richtigen Variablen zu.

Hätte mir klar sein müssen/sollen.
Fazit: with..do lohnt wirklich nur bei extrem kurzen Abschnitten, in denen keine Mehrdeutigkeiten auftreten können.

Danke an euch alle.
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#8

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 13:57
Zitat:
Fazit: with..do lohnt wirklich nur bei extrem kurzen Abschnitten
...wie du siehst überhaupt nicht. Dann ergänze mal deinen Code z.B... Plötzlich kommt was anderes raus als früher. Es muß nicht immer eine AV sein.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: Funktionsaufruf innerhalb With..do => access violation

  Alt 6. Mär 2017, 15:04
Diese Beispiele sind extrem verkürzt, machen aber hoffentlich klar, dass auch bei korrekter Syntax und Kompilierbarkeit von Quelltext bei der Verwendung von With "Namenskonflikte" auftreten können.

D. H.: Es kann sein, dass bei mehreren gleichnamigen Eigenschaften unterschiedlicher Objekte .......
Delphi-Quellcode:
//var R: TRect;
with R do begin
  Width := Right - Left;
end;
Früher traf es Form.Width bzw. Self.Width und nun Delphi-Referenz durchsuchenTRect.Width
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz