AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

BPL Zugriffsverletzung

Ein Thema von haentschman · begonnen am 20. Jul 2014 · letzter Beitrag vom 20. Jul 2014
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von haentschman
haentschman

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

BPL Zugriffsverletzung

  Alt 20. Jul 2014, 11:09
Hallo Alle...

Ich glaube das ich einen kleinen Fehler übersehen habe... Da hagelt es Zugriffsverletzungen incl. rtl150.bpl Instanziere ich die Klasse direkt läuft die Anwendung perfekt. Also mache ich beim Verwenden der BPL wahrscheinlich einen grundsätzlichen Fehler. Ich habe jetzt schon so viel Zeit investiert. Darum ist eure Hilfe nun notwendig.


Ziel:
Auslagerung einer Klasse und dynamische Verwendung. Rückgabe eines Interfaces. Verwendung des Interfaces in verschiedenen Threads unabhängig voneinander.

Klasse:
Delphi-Quellcode:
TXWebBaseParser = class(TInterfacedObject, IDVAParser)
.
TXWeb_500_V1_2Parser = class(TXWebBaseParser)

Funktionsbeispiel der Klasse (wahrscheinlich nicht relevant):

Delphi-Quellcode:
procedure TXWebBaseParser.ParseName(const aText: PChar; MasterDevice: TMasterDevice);
var
  sl: TStringList;
  I,J: Integer;
begin
  sl:= TStringList.Create;
  try
    sl.Text:= aText;
    for I:= 0 to sl.Count - 1 do
    begin
      if AnsiStartsText('var n_ins',sl[I]) then
      begin
        for J:= 14 to Length(sl[I]) do
        begin
          if sl[I][J] = '"then
          begin
            MasterDevice.Caption:= Copy(sl[I],14,J - 14);
            Break;
          end;
        end;
      end;
      if AnsiStartsText('var d_ins',sl[I]) then
      begin
        for J:= 14 to Length(sl[I]) do
        begin
          if sl[I][J] = '"then
          begin
            MasterDevice.Name:= Copy(sl[I],14,J - 14);
            Break;
          end;
        end;
      end;
    end;
  finally
    sl.Free;
  end;
end;
Direktverwendung funktioniert:
Delphi-Quellcode:
FParser: IDVAParser;
.
.
procedure TDVAParser.LoadBpl;
begin
  FParser:= TXWeb_500_V1_2Parser.Create;
// FBpl:= 'D:\tmp_1\Debug\Win32\XWEB_500_V1_2_1.bpl';
// FMasterDeviceBplHandle:= LoadPackage(PChar(FBpl));
// if FMasterDeviceBplHandle <> 0 then begin
// FCreateParser:= GetProcAddress(FMasterDeviceBplHandle, 'CreateParser');
// FParser:= FCreateParser;
// end
// else
// begin
// raise Exception.Create('BPL ' + QuotedStr(FBpl) + ' konnte nicht geladen werden.');
// end;
end;
Function für Interface in der BPL:
Delphi-Quellcode:
function CreateParser: IDVAParser;
begin
  Result:= TXWeb_500_V1_2Parser.Create;
end;

exports
  CreateParser;
Beispiel BPL:
Delphi-Quellcode:
FParser: IDVAParser;
.
.
procedure TDVAParser.LoadBPL;
begin
// FParser:= TXWeb_500_V1_2Parser.Create;
  FBpl:= 'D:\tmp_1\Debug\Win32\XWEB_500_V1_2_1.bpl';
  FMasterDeviceBplHandle:= LoadPackage(PChar(FBpl));
  if FMasterDeviceBplHandle <> 0 then begin
    FCreateParser:= GetProcAddress(FMasterDeviceBplHandle, 'CreateParser');
    FParser:= FCreateParser; // Interface wird zurückgegeben
  end
  else
  begin
    raise Exception.Create('BPL ' + QuotedStr(FBpl) + ' konnte nicht geladen werden.');
  end;
end;
Problem:
Bei Verwendung der BPL bekomme ich Zugriffsverletzungen aus den verschiedensten Bereichen. Angeblich sind Listen nil usw. Da die Listen außerhalb der BPL erzeugt werden und nur der Klasse zum Füllen übergeben werden kann ich manches nur als Nebeneffekt bezeichnen. Bei BPL sollte das eigentlich uneingeschränkt funktionieren.

Danke für Info´s. Bitte beschränkt euch bei der Diskussion auf die Zielaufgabe. Das Projekt ist schon komplex genug und fortgeschritten

Geändert von haentschman (20. Jul 2014 um 21:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.349 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: DLL, BPL Zugriffsverletzung

  Alt 20. Jul 2014, 16:28
Das sieht soweit erst einmal gut aus sofern TMasterDevice keine Klasse ist. Die Frage ist aber wie das Interface aussieht. Erstens dürfen in dem Interface selbst keinerlei Objektreferenzen vorkommen. Bei Packages sollte zwar auch das funktionieren, macht aber normalerweise keinen Sinn, da du dir dann auch das Interface sparen kannst.

Sinnvoller ist wirklich alles mit Interfaces zu machen. Denn sonst mischst du verschiedene Lebenszyklen von Objekten und Interfaces, das gibt nur Probleme.

Und zweitens musst du schauen, dass auch die Datentypen passen, z.B. dass keine Strings vorkommen (nur WideStrings oder PChars etc.).

Dazu kommen dann noch Threads. Wenn das Interface von mehreren Threads verwendet wird, musst du sichergehen, dass darin nicht auf irgendwelche threadübergreifenden Felder ohne Synchronisation bzw. Locks zugegriffen wird.

Ohne mehr Quelltext lässt sich dazu aber nur schwer etwas sagen. Gerade Probleme mit Threading oder Interfaces lassen sich nicht so einfach aus der Ferne diagnostizieren.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: DLL, BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:00
Danke für die Antwort...

Ich hätte noch erwähnen sollen, das es viele verschiedene Klassen sind die jeweils in eine BPL ausgelagert sind / werden sollen. Daher macht das Interface schon Sinn. Alle Klassen implementieren das gleiche. Hintergrund ist, das der Thread sich nur seine zur Konfiguration passende BPL (nämlich den Parser) lädt. Haben 2 Threads die gleiche Konfiguration (wie durch die Festverdrahtung im Beispiel) ist das Handle natürlich gleich. Unabhängig davon sollte aber das CreateParser verschiedene Referenzen (Instanzen) des Interfaces liefern.
Zitat:
Erstens dürfen in dem Interface selbst keinerlei Objektreferenzen vorkommen.
Wo steht das? Bei DLL kann ich das nachvollziehen. Bei BPL nicht.
Zitat:
Wenn das Interface von mehreren Threads verwendet wird, musst du sichergehen, dass darin nicht auf irgendwelche threadübergreifenden Felder ohne Synchronisation bzw. Locks zugegriffen wird.
Das ist ausgeschlossen. Der Thread übergibt dem Parser den Response und die im Thread erzeugte Liste. Der Parser macht die Liste dann voll. Also greift der Parser nicht threadübergreifend auf anderes zu.
Zitat:
Denn sonst mischst du verschiedene Lebenszyklen von Objekten und Interfaces, das gibt nur Probleme.
Im Falle des Füllens der Objektliste mit den im Parser erzeugten Objekten hast du Recht da die Objekte in der "Speicherverwaltung" der BPL liegen. Wenn man genau weis was man wann tut ist das eher kein Problem. Damit meine ich selbst in der korrekten Reihenfolge aufräumen.
Delphi-Quellcode:
IDVAParser = interface(IInterface)
    ['{7082CCBB-2680-4BC4-8B17-7FFE1D602A0A}']

    procedure ParseDevice(const aText: PChar; DeviceList: TDeviceList);
    procedure ParseDeviceGroup(const aText: PChar; DeviceGroupList: TDeviceGroupList);
    procedure ParseDeviceModel(const aText: PChar; ModelList: TDeviceModelList);
    procedure ParseDeviceParameterGroup(const aText: PChar; DeviceParameterGroupList: TDeviceParameterGroupList);
    procedure ParseDeviceParameters(const aText: PChar; Parameters: TDeviceParameterList);
    procedure ParseAlarmState(const aText: PChar; AlarmStateList: TAlarmStateList);
    procedure ParseAlarmType(const aText: PChar; AlarmTypeList: TAlarmTypeList);
    procedure ParseAlarm(const aText: PChar; AlarmList: TAlarmList);
    procedure ParseName(const aText: PChar; MasterDevice: TMasterDevice);
    procedure ParseRuntime(const aText: PChar; RuntimeList: TRuntimeList);
    function ParseUser(const aText: PChar): PChar;
    procedure ParseVersion(const aText: PChar; MasterVersion: TMasterDeviceVersion);
    procedure ParseSystem(const aText: PChar; MasterDevice: TMasterDevice);
    procedure ParseRunningState(const aText: PChar; MasterDevice: TMasterDevice);
    procedure ParseRecordData(const aText: PChar; RecordDataList: TRecordDataList);
    function GetParameterString(aType: TDVA_CommunicationStringType): PChar;
    function GetSourceString(aType: TDVA_CommunicationStringType): PChar;
  end;
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: DLL, BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:06
Wieso du bei so einem Interface überhaupt das Thema DLL ansprichst ist mir schleierhaft und lenkt doch nur ab, weil das eben nicht funktioniert. Ändere doch das Thema und streiche alles was auf DLL hinweist

Und da DLL eh rausfällt und nur BPL übrig bleibt, wozu dann als Parameter mit PChar arbeiten?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (20. Jul 2014 um 19:09 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: DLL, BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:23
Warum reagierst du eigentlich gleich so pikiert. Ja, andere können es besser! Muß ich mich bei dir entschuldigen daß ich verschiedene Sachen ausprobiert habe und auch aus Fehlern lerne?
Die ganze Geschichte der Auslagerung hat noch nie funktioniert. Da ist es mir jetzt gerade völlig Wurst ob PChar oder String. Wenn das Grundkonstrukt funktioniert, ich die Fehler verstanden habe, kann man sich über den Rest Gedanken machen.

Danke.

Nachtrag: Ich tue dir den Gefallen...

Geändert von haentschman (20. Jul 2014 um 19:25 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:33
Eine BPL ist praktisch auch nur eine etwas aufgemotzte DLL und wenn man die BPL nicht gegen die richtigen/nötigen Laufzeitpackaged link, was man bei der DLL aber auch machen kann,
dann läuft man bei der BPL dennoch in die selben Probleme, wie bei DLLs, während man in DLLs auch die selben Vorteile der BPL einkompilieren kann, wenn man Laufzeitpackages nutzt.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:40
Danke für deinen Senf.. Hilft mir das mit dem BPL Versändnis weiter? Wenn ja wie...
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.349 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:42
Delphi-Quellcode:
IDVAParser = interface(IInterface)
    ['{7082CCBB-2680-4BC4-8B17-7FFE1D602A0A}']

    procedure ParseDevice(const aText: PChar; DeviceList: TDeviceList);
...
  end;
So ähnlich sieht das bei uns auch aus, allerdings sind das dann nicht Parameter vom Typ TDeviceParameterList sondern vom Typ IInterfacedList<IDeviceParameter>...

Deine Funktionen sehen ja so aus als ob die Objekte nur übergeben und innerhalb der Funktion verwendet werden. Insofern hast du mit dem Lebenszyklus auch keine Probleme (da du Interfaces und Objekte mischst). Allerdings heißt die BPL-Hölle nicht umsonst so. Ganz sorglos mit Objekten werfen kann man da auch nicht.
Allerdings weiß ich das nicht genauer, da ich immer sauber komplett mit Interfaces gearbeitet habe und das Problem daher nie hatte.

Hast du vielleicht einmal einen Stacktrace von einem solchen Fehler und den Quelltext an der Stelle und kannst das zeigen?
Generell:
Wenn irgendwo nil drin steht, wo es nicht drin stehen sollte, würde ich das ganze in Getter und Setter auftrennen und einen Haltepunkt auf den Setter setzen mit "wenn nil übergeben wird" als Bedingung. Alternativ könntest du auch einen Datenhaltepunkt nutzen.

Zitat:
Erstens dürfen in dem Interface selbst keinerlei Objektreferenzen vorkommen.
Wo steht das? Bei DLL kann ich das nachvollziehen. Bei BPL nicht.
Das habe ich ja auch geschrieben, bei BPL geht es. Allerdings macht dann das Interface wenig Sinn, dann kannst du auch gleich konsistent bleiben und ein Objekt zurückgeben. Mischen von Objektreferenzen und Interfaces ist immer schlecht.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: BPL Zugriffsverletzung

  Alt 20. Jul 2014, 19:47
Zitat:
dann kannst du auch gleich konsistent bleiben und ein Objekt zurückgeben
...sind viele verschiedene Objekte da der Parser sich in der Funktion unterscheiden kann (Text unterschiedlich) Deshalb das Interface. Der Thread arbeitet mit dem Interface. Da ist es wurscht ob Tbla oder TBlubb hinten dran hängt.

Meinst du wenn ich statt der Objektliste eine Interface Liste übergebe und die (zu ergänzenden) Interfaces der im Parser erzeugten Objekte hineinlege habe ich weniger Probleme?
Zitat:
Hast du vielleicht einmal einen Stacktrace von einem solchen Fehler
...nicht als Bild. Die letzte Zeile vor einer der Zugriffsverletzungen war:
Delphi-Quellcode:
procedure TXWebBaseParser.ParseAlarm(const aText: PChar; AlarmList: TAlarmList);
var
  aAlarm: TAlarm;
  I, PositionFirst, PositionCount, TempPosition: Integer;
  sl: TStringList;
begin
  AlarmList.Clear; //<- hier. Klingt als wäre die Objektliste nicht existent. Diese wird aber beim Erzeugen des Threads erzeugt und im Destroy freigegeben.
  sl := TStringList.Create;
.
.
...deshalb vermute ich die Fehler in der Speicherverwaltung weil ich mit den Objekten nicht richtig umgehe. Mich interessiert halt wie es richtig geht. Deine Variante, grundsätzlich alles mit Interfaces, werde ich mal ausprobieren. Leider erst nächstes Wochenende.

Danke...

Geändert von haentschman (20. Jul 2014 um 19:54 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.349 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: BPL Zugriffsverletzung

  Alt 20. Jul 2014, 20:15
Klingt als wäre die Objektliste nicht existent. Diese wird aber beim Erzeugen des Threads erzeugt und im Destroy freigegeben.
FreeOnTerminate nutzt du aber hoffentlich nicht, oder? Denn dann dürftest du auf das Threadobjekt nicht von außen zugreifen.

Das würde das aber direkt erklären.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 23:32 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