Access Violation by Get/Set Variable

Hallo,

Beschäftige mich jetzt seit einigen Tagen jetzt mit dem SDK und hab mittlerweile auch schon einige Erfolgserlebnisse hinter mir.

Bin jetzt allerdings aber auf einen Fehler gestoßen, den ich nicht in den Griff bekomme: Access Violation – mein absoluter lieblings Fehler in Delphi…
Konnte in mittlerweile auch Example Module vom Kollegen Tommi reproduzieren (besten Dank an dieser Stelle gleich mal für das Beispiel, hat mir einen relativ leichten Einstieg in die Module Erstellung ermöglicht).

Konkret geht es um das Setzen und Auslesen von String Variablen, kann den Fehler mit folgendem Code reproduzieren:


   MyDevice_setLine(23967 /*[Tests\TestModule\MyLogger]*/, "1234567890");
   MyDevice_setLine(23967 /*[Tests\TestModule\MyLogger]*/, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
   $txt = MyDevice_getLine(23967 /*[Tests\TestModule\MyLogger]*/);

Fehler tritt erst auf wenn der String > 80 Zeichen wird.

Hoffe mir kann da einer der “SDK Götter” weiterhelfen

Beste Dank und Grüsse
Andreas

Welche Delphi Verison? Wenn TurboDelphi… hast du FastMM4 in den uses?

MyDevice_setLine -> kannst du zeigen, was da drin ist?

paresy

CodeGear™ RAD Studio 2007 Version 11.0.2804.9245

FastMM4 hab ich in den Uses drinnen (hab mir eine Version aus dem Internet geladen und den SourceCode zum SDK gelegt, selbiges für gnugettext.). - gibts da bestimmte Versionen die man verwenden sollte ?

SourceCode sieht im wesentlichen so aus:


function TIPSDevice.getLine:string;stdcall;
begin
   LogMessage(KL_DEBUG,'GetLine entered...');
   SendData('getLine','entered');
   result:=lastLine;
   SendData('getLine','Finshed, Result:'+result);
end;

function TIPSDevice.setLine(Text:string):integer;stdcall;
begin
   LogMessage(KL_DEBUG,'SetLine entered...');
   senddata('setLine','entered');
   handleData('PHP',Text);
   Result:=length(Text);
end;

procedure TIPSDevice.HandleData(From,Text:string);
  var s:string;
begin
   LogMessage(KL_DEBUG,'Handle Data entered');
   senddata('HandleData','entered');
   s:=from+' -->'+Text;
   lastline:=s;
   logme(s);
   DoEcho(Text);
   fKernel.VariableManager.WriteVariableString(GetStatusVariableID('LastLineVariable'), s);
   senddata('HandleData','finished');
end;

Werd mein eigenes Projekt heute abend nochmals etwas abspecken und auf das wesentliche reduzieren.

Eventuell hab ich auch wirklich nur eine falsche Version von FastMM4 - hatte gar nicht mehr daran gedacht, dass ich mir da eine Version aus dem Netz gesaugt hatte …

lg
Andreas

Haste mal den Debugger angemacht und geguckt wo der Fehler genau auftritt?!

paresy

Debugger habe ich noch nicht geschafft mit der IPS.exe zum Laufen zu bringen .

Konnte den Fehler trotzdem eingrenzen:


procedure TIPSDevice.HandleData(From,Text:string);
var s:string;
begin
   s:=from+' -->'+Text;
   fKernel.VariableManager.WriteVariableString(
      GetStatusVariableID('LastLineVariable'), s);
end;

der Fehler passiert in der Zeile: s:=from+’ -->’+Text;
wenn man aber die Zeile danach mit dem VariableManager auskommentiert funktionierts wieder - hab keine Idee wie es zu so einem Phänomen kommen kann ???

Na ja, für heute reichts mir auf jeden Fall mal …

lg
Andreas

so, bin jetzt wieder einen Schritt weiter, Debugger läuft, allerdings kann ich mit dem Debugger die AV in Tommis Sample Project nicht reproduzieren.

Reproduzieren kann ich bei meinem eigenen Projekt eine AV im Konstruktor,
sobald ich mit der Maus auf „fKernel.VariableManager“ steht „Auswerten“ und ab diesen Zeitpunkt geht nichts mehr (abgesehen von einem Programmabbruch).

@parsey
Welche Version von FastMM4 bzw. gnugettext it zu empfehlen (Link für Download)?

lg
Andreas

FastMM kannst du bei deinem D2007 rausnehmen. D2007 hat es direkt mit drin. gettext Version sollte egal sein.

Hast du mal das mitgelieferte DemoProjekt kompiliert?

paresy

Das DemoProjekt kompiliert ohne Probleme, benötige jetzt auch meine FastMM4 Version nicht mehr.

habe jetzt folgenden Code in das Demo-Projekt eingefügt:


procedure TIPSTestModule.TestFunction; stdcall;
var
  i:integer;
  msg:string;
begin
  for I := 0 to 99 do
  begin
     senddata('TestFunction', 'Prepare String, Idx='+IntToStr(i));
     msg := msg + '1234567890';
     senddata('TestFunction', 'Write Variable, Idx='+IntToStr(i));
     fKernel.VariableManager.WriteVariableString(
        GetStatusVariableID('TestVariable'), msg);
  end;
end;

beim Ausführen der Funktion


<?
   TM_TestFunction(33414);
?>

bekomme ich dann beim 10. Durchlauf der Schleife eine AV !!!

Kann das mal wer verifizieren - bin ich wirklich das einzige arme Schwein, der diese AV bekommt …

lg
Andreas

Schau doch mal nach, dass in den Compileroptionen „HugeStrings“ aktiviert ist. Sonst kann ein String nur 255Bytes aufnehmen. 100x10Byte sind aber schon 1000. Ich weiss jetzt nicht, was im SDK intern beim Variablenmanager verwendet wird, evtl. gibt es dort auch noch ein Limit .

Tommi

ja, HugeStrings ist aktiviert, werd mal schauen, ob ich mit dem Debugger noch was rausfinde.

Hallo paresy,

bin jetzt schön langsam mit meinem Latein am Ende, sobald ich fKernel.VariableManager etwas exzessiver benütze, laufe ich in eine AV hinein:
Zwei Fragen:
1.) Kannst Du ausschließen, dass es sich hierbei um einen Bug im SDK handelt.
2.) Was könnte ich sonst noch versuchen (TurboDelphi habe ich noch nicht versucht, kann mir aber nicht vorstellen, dass das was ändert).

Wollte mir eigentlich einen kleinen Logger mit WebFront Interface basteln, aber unter den Voraussetztungen muss ich mein Projektchen wohl „kübeln“.

Hier noch die Sourcen, ansonsten alles gleich wie im Demo Projekt:


interface

uses Windows, Messages, SysUtils, ActiveX, Classes, Forms, StdCtrls,
     Dialogs, StrUtils, ExtCtrls, ScktComp, WinSock,
     UIPSTypes, UIPSModuleTypes, UIPSDataTypes;

type
 IIPSTestModule = interface(IInvokable) ['{C503D47C-32B0-442B-A945-D1D7EBBF6621}']
  procedure TestFunction; stdcall;
 end;

 TIPSTestModule = class(TIPSModuleObject,
                        IIPSModule,
                        IIPSTestModule
                        )
  private
  public
   constructor Create(IKernel: IIPSKernel; InstanceID: TInstanceID); override;
   destructor  Destroy; override;

   procedure LoadSettings(); override;
   procedure SaveSettings(); override;
   procedure ResetChanges(); override;
   procedure ApplyChanges(); override;

   procedure TestFunction; stdcall;

   class function GetModuleID(): TStrGUID; override;
   class function GetModuleType(): TIPSModuleType; override;
   class function GetModuleName(): String; override;
 end;

implementation
//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleID(): TStrGUID;
begin
 Result := GUIDToString(IIPSTestModule); //Will return Interface GUID
end;

//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleType(): TIPSModuleType;
begin
 Result := mtDevice;
end;

//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleName(): String;
begin
 Result := 'TestModule';
end;

//------------------------------------------------------------------------------
constructor TIPSTestModule.Create(IKernel: IIPSKernel; InstanceID: TInstanceID);
begin
 inherited;
 RegisterVariable('TestVariable', 'TestVariable', vtString, '');
 ConstructorPostProcess;
end;

//------------------------------------------------------------------------------
destructor  TIPSTestModule.Destroy;
begin
 DestructorPreProcess;
 inherited;
end;

//------------------------------------------------------------------------------
procedure TIPSTestModule.LoadSettings();
begin
 inherited;
end;

//------------------------------------------------------------------------------
procedure TIPSTestModule.SaveSettings();
begin
 inherited;
end;

//------------------------------------------------------------------------------
procedure TIPSTestModule.ResetChanges();
begin
 inherited;
end;

//------------------------------------------------------------------------------
procedure TIPSTestModule.ApplyChanges();
begin
 inherited;
end;

//------------------------------------------------------------------------------
procedure TIPSTestModule.TestFunction; stdcall;
var
  i:integer;
  msg:string;
begin
  for i := 0 to 20 do
  begin
     senddata('TestFunction', 'Prepare String, Idx='+IntToStr(i));
     msg := msg + '1234567890';
     senddata('TestFunction', 'Write Variable, Idx='+IntToStr(i));
     fKernel.VariableManager.WriteVariableString(GetStatusVariableID('TestVariable'), msg);
  end;
end;
end.

Andreas

Bei mir funktioniert das Demo-Modul mit der „Testfunktion“ problemlos.
Quelltext und Binary im Anhang.

Tommi

mymoduledll.zip (294 KB)

MyModule.zip (73.8 KB)

OK, besten Dank, gibt mehr jedenfalls mal die Gewissheit, dass es an meiner Delphi Version liegen muss (hab mittlerweile auch schon das Betriebssystem gewechselt - Win7 auf XP).

habe include von FastMM4 enfernt (sollte ja bei meiner Delphi Version dabei sein), Pfad für SDK angepasst, compile (meine DLL ist etwas grösser), in IPS kopiert …

Deine DLL funktioniert problemlos, sobald ich meine kompilierte Version verwende fliege ich nach dem 4. Aufruf der Funktion SetLine auf die „Fresse“ .

CodeGear™ Delphi® 2007 für Win32® Version 11.0.2804.9245

Wenn Du noch eine Idee hast - bitte um Info

Danke
Andreas

MyModule.zip (586 KB)