Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - DLL -> INVALID POINTER OPERATION


peeage - Di 07.08.07 10:50
Titel: DLL -> INVALID POINTER OPERATION
Morje zusammen...

Hab da ein Problem:


Ich hab mir eine DLL mit einer funktion zusammengebastelt, an welche ein ARRAY of String übergeben wird. Die in dem ARRAY (größe = dynamisch) enthaltenen Strings werden umformatiert und in einem neuen ARRAY (result) zurückgegeben.

DLL


Delphi-Quelltext
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:
[...]

type
  ROrdner = record
    Name: String;
    Verknuepfung: Integer;
  end;
  result_ARRAY = ARRAY of ARRAY of ROrdner;


[...]


function ADInputTOfilestructure(ARRAY_incoming: ARRAY of String): result_ARRAY stdcall;
var [...]
begin

[ ... CODE ... ]
 
end;

exports
       ADInputTOfilestructure;

begin
end.



EXE


Delphi-Quelltext
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:
[...]

type
  ROrdner = record
    Name: String;
    Verknuepfung: Integer;
  end;
  result_ARRAY = ARRAY of ARRAY of ROrdner;

[...]

implementation

function ADInputTOfilestructure(ARRAY_incoming: ARRAY of String): result_ARRAY; stdcall;
external 'dll\Project2.dll';


[...]


procedure TForm1.Button1Click(Sender: TObject);
var Ordner: result_ARRAY;
begin

  Ordner:= ADInputTOfilestructure(ARRAY_);     // Hier wird ein ARRAY of String an die Funktion in der DLL übergeben
  showMessage(Ordner[1,1].Name);               // Hier soll Testweiste ein Inhalt des Rückgabearrays ausgegeben werden

end;




Wenn ich nun im Programm den Button betätige, bekomme ich zuerst den Inhalt von Ordner[1,1].Name ausgegeben und folgend die Meldung "INVALID POINTER OPERATION".

An dem Sourcecode in der DLL liegts keinesfalls. Ich hab es mal mit ner ganz einfachen Funktion probiert -> ARRAY of String übergeben, Inhalt von ARRAY[0] modifizieren und ARRAY zurückgeben .... Dabei kommt der gleiche Fehler.


Wenn ich aber in der DLL und im eigentlich Programm aus


Delphi-Quelltext
1:
2:
type
  result_ARRAY = ARRAY of String;


... folgendes mache ...


Delphi-Quelltext
1:
2:
type
  result_ARRAY = ARRAY [0..5of String;



dann funktionierts wunderbar ;)


kann mir jemanden helfen?


peeage - Di 07.08.07 11:04

Das Problem hat sich soeben gelöst.


Wen es interessiert: Es muss in der DLL + im eigentlichen Programm die Unit ShareMem eingebunden werden.


Delphi-Quelltext
1:
uses ShareMem;                    


Stefan.Buchholtz - Di 07.08.07 11:08

Typen mit dynamischer Speicherverwaltung (Strings, dynamische Array, Varianten) lassen sich nicht so einfach zwischen einer DLL und dem Hauptprogramm austauschen. Speicher für diese Typen wird vom Delphi-Speichermanager verwaltet, wobei Hauptprogramm und DLL jede normalerweise jeweils einen eigenen haben. Wenn man dann dynamische Typen zwischen Programm und DLL austauscht, kommen sich die gegenseitig in die Quere und es kracht.

Dafür gibt es drei Abhilfen

1.) Zum Datenaustausch nur Typen mit fester Größe (statische Arrays, Strings mit expliziter Längenangabe) verwenden.
2.) Dynamischen Speicher selbst via GetMem und FreeMem verwalten. Dabei gilt: Jeder muss seinen Speicher selbst aufräumen. Wenn die DLL Daten in einem via GetMem angeforderten Speicherbereich zurückgibt, bruachst du eine zusätzliche DLL-Funktion, um diesen Speicher auch in der DLL wieder freizugeben - macht das Hauptprogramm FreeMem auf einen Speicherblock, der in der DLL erzeugt wurde oder umgekehrt, knallt es.
3.) Den gemeinsamen Speichermanager ShareMem verwenden. Dazu müssen Hauptprogramm und DLL die Unit ShareMem jeweils als erstes in der Projektdatei einbinden. Ausserdem muss zum Programm die Delphi beigelegte BORLNDMM.DLL mit installiert werden.

Stefan