IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision + DIE LÖSUNG!

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision + DIE LÖSUNG!

Post by cgaertner »

Liebe Alle,

dieses Thema ist ähnlich, wie mein gestriges, denn ich versuche weiterhin, den IO-Warrior 24 mit FreePascal unter Linux anzusprechen. Dabei bin ich möglicherweise auf Probleme mit der Library gestoßen, denn ich habe nach immer wieder auftretendem Absturz und stundenlanger Suche den Fehler eingrenzen können. Ich habe ein Testprogramm geschrieben, das aus folgenden stark reduzierten Units besteht:

Code: Select all

unit iowkit;

interface

const
  IOWKIT_VENDOR_ID        = $07c0;
  IOWKIT_PRODUCT_ID_IOW24 = $1501;
  IOWKITDllName           = 'libiowkit.so';

type
  IOWKIT_HANDLE = Pointer;

function IowKitOpenDevice: IOWKIT_HANDLE; stdcall;
procedure IowKitCloseDevice(devHandle: IOWKIT_HANDLE); stdcall;
function IowKitVersion: PChar; stdcall;
function IowKitGetProductId(devHandle: IOWKIT_HANDLE): Cardinal; stdcall;
function IowKitGetRevision(devHandle: IOWKIT_HANDLE): Cardinal; stdcall;

implementation

function IowKitOpenDevice: IOWKIT_HANDLE; stdcall; external IOWKITDllName name 'IowKitOpenDevice';
procedure IowKitCloseDevice(devHandle: IOWKIT_HANDLE); stdcall; external IOWKITDllName name 'IowKitCloseDevice';
function IowKitVersion: PChar; stdcall; external IOWKITDllName name 'IowKitVersion';
function IowKitGetProductId(devHandle: IOWKIT_HANDLE): Cardinal; stdcall; external IOWKITDllName name 'IowKitGetProductId';
function IowKitGetRevision(devHandle: IOWKIT_HANDLE): Cardinal; stdcall; external IOWKITDllName name 'IowKitGetRevision';
end.

Code: Select all

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  SysUtils, Forms, Dialogs, StdCtrls, iowkit, Classes;

type

  { TForm1 }
  TForm1 = class(TForm)
    Button3: TButton;
    procedure Button3Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure test1();
var
  ioHandle: IOWKIT_HANDLE = nil;
begin
  ShowMessage ('Bibliothek Version: ' + IowKitVersion);
  ioHandle := IowKitOpenDevice();
  if Assigned(ioHandle) then begin
    if (IowKitGetProductId(ioHandle) = IOWKIT_PRODUCT_ID_IOW24) then begin
      ShowMessage ('Es wurde ein IO-Warrior 24 gefunden!');
    end;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  test1();
end;

end.
Die Form hat einen Button und beim Anklicken wird die Prozedur "test1()" aufgerufen. Sie sollte die Version der Library ausgeben (funktioniert: "Bibliothek Version: IO-Warrior Kit V1.7.0.21") und dann - falls ein IO-Warrior 24 als erstes Gerät gefunden wurde - eine Meldung. Leider erhalte ich beim Ausführen dieses Programmes nach der Ausgabe der Meldung (also nicht beim Aufruf von "IowKitGetProductId", sondern beim Verlassen der Prozedur) eine Exception ("Projekt project1 hat Exception-Klasse »External: SIGSEGV« ausgelöst. Bei Adresse 80720DE").

Und jetzt wird es kurios: wenn ich die Zeile ...
if (IowKitGetProductId(ioHandle) = IOWKIT_PRODUCT_ID_IOW24) then begin
durch diese Zeile ersetze ...
if (IntToStr(IowKitGetProductId(ioHandle)) + ' ' = IntToStr(IOWKIT_PRODUCT_ID_IOW24) + ' ') then begin
... dann funktioniert es. Sprich, ich vergleiche nicht den Rückgabewert von IowKitGetProductId mit IOWKIT_PRODUCT_ID_IOW24, sondern wandle die Werte in einen String um und hänge ein Leerzeichen an.

Dieses Leerzeichen ist wichtig, denn wenn ich mir in oberem Beispiel statt der if-Abfrage die Kit-Revision anzeigen lassen möchte, führt der Befehl ...
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
... zu einem Absturz, wogegen der Befehl ...
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)) + ' ');
... erfolgreich ist - wieder macht das Leerzeichen am Ende den Unterschied!

Das Problem habe ich übrigens nur mit den Befehlen "IowKitGetProductId" und "IowKitGetRevision" feststellen können, alle anderen Befehle funktionieren tadellos. Wenn ich diese Befehle nicht verwende, kann ich unter Linux genauso auf den IO-Warrior 24 zugreifen wie unter Windows und erfolgreich Daten auslesen.

Es fällt auf, daß die beiden Befehle einen Rückgabewert vom Typ "Cardinal" haben. Aber egal ob ich den Wert direkt weiterverwende (und z.B. mit IOWKIT_PRODUCT_ID_IOW24 vergleiche) oder mit IntToStr umwandle, das Ding stürzt ab, außer ich hänge noch ein beliebiges Zeichen an. Da liegt ja die Vermutung nahe, daß da ein String nicht korrekt terminiert sein könnte, aber da der String ja von IntToStr (Systemroutine) aus Cardinal erzeugt wird, sollte die Terminierung ja passen, da sie vom System erledigt wird????

Und ich habe soeben festgestellt, daß der Absturz nur kommt, wenn ich in einer Prozedur als letzten Library-Befehl eine Variante ohne Leerzeichen am Ende ausführe. Folgendes Programm stürzt ab:

Code: Select all

  ShowMessage ('Bibliothek Version: ' + IowKitVersion);
  ioHandle := IowKitOpenDevice();
  if Assigned(ioHandle) then begin
    ShowMessage (IntToStr(IowKitGetrevision(ioHandle))+' ');
    ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
  end;
Folgendes Programm läuft (nur die beiden Zeilen wurden vertauscht!):

Code: Select all

  ShowMessage ('Bibliothek Version: ' + IowKitVersion);
  ioHandle := IowKitOpenDevice();
  if Assigned(ioHandle) then begin
    ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
    ShowMessage (IntToStr(IowKitGetrevision(ioHandle))+' ');
  end;
Zunächst dachte ich, ich bin verrückt, wenn das Programm einmal geht und dann wieder nicht. Dann habe ich die Sache mit der Reihenfolge der Befehle bemerkt. Nun fühle ich mich nicht mehr verrückt, sondern ratlos. Übersehe ich in meiner Betriebsblindheit etwas total Offensichtliches? Habe ich irgendwas in der Dokumentation verpaßt?

Ach ja: es ist Debian 10, 32 Bit, Lazarus 2.0.0+dfsg-2 mit der FPC-Version 3.0.4.

LG Christian
Last edited by cgaertner on Sun Aug 02, 2020 12:53 pm, edited 1 time in total.
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

Re: IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision

Post by cgaertner »

PS: Ach ja, das alles läuft in einer virtuellen Maschine unter VMware 15. Aber da der Rest ja auch funktioniert, halte ich das als Ursache des Problems für eher unwahrscheinlich.
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

Re: IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision

Post by cgaertner »

PPS: Folgende Codezeilen sorgen auch für einen Absturz unter Linux ("Projekt test1 hat Exception-Klasse »External: SIGSEGV« ausgelöst. Bei Adresse 80710DE"). Allerdings nicht bei meinem kleinen Testprogramm von oben, sondern nur bei meinem großen echten Projekt. Deshalb habe ich noch nicht ganz herausfinden können, was sonst noch für Randbedingungen zutreffen müssen.

Code: Select all

if Assigned(ioHandle) then begin
  IowKitCloseDevice(ioHandle);
end;
Um es bei der Gelegenheit klar zu sagen: ich bin überzeugt, daß ich irgendwas übersehen habe bzw. falsch mache und will hier keinesfalls der Library von CodeMercs Fehler bzw. Bugs unterstellen. Ich würde nur gerne wissen, was ich übersehen habe bzw. falsch mache - zumal der exakt gleiche Code (und zwar wirklich 1:1) seit Monaten unter Windows tadellos funktioniert.

Viele Grüße,
Christian
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

Re: DIE LÖSUNG!!!!

Post by cgaertner »

Liebe Alle,

ich habe die Lösung gefunden!!!! :-)

In einem 13 Jahre alten Beitrag von Robert Marquardt (Danke!) hier im Forum stand der Satz "Es muesste eigentlich genuegen stdcall durch cdecl zu ersetzen (...)", den ich bisher überlesen bzw. dessen Bedeutung ich nicht erkannt habe.

Nachdem ich die Deklarationen der Funktionen entsprechend geändert habe - also zum Beispiel ...

Code: Select all

function IowKitOpenDevice: IOWKIT_HANDLE; cdecl;
... statt ...

Code: Select all

function IowKitOpenDevice: IOWKIT_HANDLE; stdcall;
... - sind sämtliche in diesem Thread erwähnten Probleme bzw. Abstürze verschwunden!

Ich hoffe, diese Information hilft vielleicht dem ein oder anderen FreePascal-Programmierer weiter.

Viele Grüße aus Wien,
Christian
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

Re: IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision

Post by cgaertner »

PS: Die Lösung mit "cdecl" gilt nur für die Linux-Version, wer (wie ich) ein Programm plattformübergreifend für Windows und Linux entwickelt, muß für die Windows-Variante weiterhin "stdcall" verwenden, sonst stürzt das Programm dort ab (Stichwort "{$IFDEF WINDOWS}" bzw. "{$IFDEF UNIX}").

Viele Grüße,
Christian
User avatar
Christoph Jung
Posts: 632
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision + DIE LÖSUNG!

Post by Christoph Jung »

Also wenn ich in ein einfachen C-Code schreibe, dann hab ich das Problem nicht. Die Funktion liefert einen unsigned long zurück und keinen String.
Evtl ist das was, das mit FreePascal zusammenhängt.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
cgaertner
Posts: 13
Joined: Sun Mar 29, 2020 2:17 am

Re: IOW24 + FreePascal + Linux: Absturz bei IowKitGetrevision + DIE LÖSUNG!

Post by cgaertner »

Christoph Jung wrote: Tue Aug 04, 2020 1:12 pm Also wenn ich in ein einfachen C-Code schreibe, dann hab ich das Problem nicht. Die Funktion liefert einen unsigned long zurück und keinen String.
Evtl ist das was, das mit FreePascal zusammenhängt.
Das ist ja auch, was ich erwartet habe und was unter Windows auch tadellos funtkioniert. Aber die beiden Aufrufvarianten stcall und cdecl unterscheiden sich (wie ich seither gelernt habe) zumindest einmal darin, wer danach den Stack bereinigt (Zitat aus Wikipedia zu stcall: "Anders als bei cdecl bereinigt die aufgerufene Funktion den Stack, nicht der Aufrufer."). Hier dürfte sich die Linux-Version der Library von der Windows-Version unterscheiden. Durch die Umwandlung in einen String und das Anhängen eines Leerzeichens geschieht vermutlich zufällig irgendwas, das den Absturz verhindert.

Danke & viele Grüße,
Christian
Post Reply