Aufbau dynamischer Arrays

Ralle

Super-Moderator , User des Jahres 2006-2007
Teammitglied
Beiträge
15.404
Reaktionspunkte
4.039
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe eine Software von festen Arrays, auf dynamische Arrays umgestellt. Vorteil ist, daß man die Größe dynamischer Arrays zur Laufzeit ändern kann. Die dynamischen Arrays kann man mit Funktionen übergeben, bei der direkten Überggabe wird automatisch ein Zeiger übergeben. Dabei ist mit aufgefallen, daß ich die Arrays immer mindestens 1-2 Byte länger machen muß, als die Nutzdaten, die ich benötige, sonst gibt es Fehlermeldungen bei Programmlauf und Abstürze. Auch bei mehrspaltigen Array treten diese Probleme auf. Weiß jemand, wie genau mehrspaltige dynamische Array aufgebaut sind, gibt es an Ende jeder Spalte eine Kennung o.ä., die diese Längendifferenz verursacht?

Programmiersprache: Delphi7
 
Zuletzt bearbeitet:
Multidimensional Arrays in D7

Hallo,

Ralle schrieb:
Weiß jemand, wie genau mehrspaltige dynamische Array aufgebaut sind, gibt es an Ende jeder Spalte eine Kennung o.ä., die diese Längendifferenz verursacht?

Nein, es gibt definitiv keine Kennung, die eine Längendifferenz verursachen kann. Multidimensionale , dynamische Arrays sind eigentlich kein Problem in Delphi, funktioniert doch ganz gut.
Entweder hast Du das Array falsch initialisiert, falsch dimensioniert, der Fehler liegt m.E. nicht in Delphi.
Kannst mir ja per PN Code-Snippets zusenden, aber der Fehler liegt bestimmt vor dem Monitor...

Gruss

Question_mark
 
Hm, ich denke es hängt mit den Funktionsaufrufen zusammen.
Ich habe das z.Bsp. mit Prodave-Mini wie folgt:

mit statischem Array:

type
plc_buffer = Array[0..1024] of Byte;

...

function DB_read ( dbno: longint; dwno: longint; var amount: longint; var plc_buffer): longint;

im Programm:
var
DBAR: plc_buffer;

...

Y[SPS] := DB_read(SimDatenListe.SimEintrag[SPS].DBSim,0,plc_amount, DBAR);

mit dynamischem Array:

type
DynBuf = array of Byte;

...

function DB_read ( dbno: longint; dwno: longint; var amount: longint; plc_buffer: DynBuf): longint;

im Programm:
var
DBAR: DynBuf;

SetLength(DBAR, SimDatenListe.SimEintrag[SPS].DB_Maximum + 6);
Y[SPS] := DB_read(SimDatenListe.SimEintrag[SPS].DBSim,0,plc_amount, DBAR);

Wenn ich + 6 verändere, dann bekomme ich beim Daten holen Fehler. Vielleicht kann ich ja DB_read aus Prodave so nicht mit dem Array versorgen, ich mußte ja die Definition der Variable in der Funktion ändern. Ich glaube inzwischen, es hängt mit der Übergabe an die Funktion zusammen, einmal das Array direkt als var plc_buffer und das andere mal ein Zeiger, denn dyn. Arrays sind bei diesem Aufruf lt. Delphi-Hilfe nichts anderes als Zeiger.

Bei den libnodave-Funktionen wird eh ein Pointer übergeben, übergebe ich den Pointer und die größe, das paßt.
 
Ich glaube inzwischen, es hängt mit der Übergabe an die Funktion zusammen, einmal das Array direkt als var plc_buffer und das andere mal ein Zeiger, denn dyn. Arrays sind bei diesem Aufruf lt. Delphi-Hilfe nichts anderes als Zeiger.
Das macht keinen Unterschied, denn var-Parameter sind auch immer Zeiger.

Was liefert denn SimDatenListe.SimEintrag[SPS].DB_Maximum ?

Ist der Wert möglicherweise zu klein ?


Gruß Axel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...aber der Fehler liegt bestimmt vor dem Monitor...

Gruss

Question_mark

davon geh ich mal ganz sicher aus :ROFLMAO:.
Nicht das dyn Array an sich ist das Problem, die nutze ich für andere Sachen im Programm ohnenhin, die Übergabe an eine Funktion ist das Problem, hier wohl eigentlich die Übergabe an eine Funktion von Prodave.

@afk

SimDatenListe.SimEintrag[SPS].DB_Maximum liefert die Bytes, die aus einem DB gelesen werden sollen + 1 Byte.

Komisch ist auch das hier:
plc_amount := SimDatenListe.SimEintrag[SPS].DB_Maximum div 2; //ist für DB_read in prodave

Bei statischen Arrays hatte ich da die gleiche Länge wie die Array-Länge stehen und es ging. Nun gabs Fehler und ich mußte div 2 einfügen (rumprobiert). Damit werden aber trotzdem alle Bytes gelesen, auch die letzten! Ist doch irgendwie nicht ganz schlüssig.

Hm. Prodave ist ja nur ein "Zusatz", aber ich will eigentlich ganz gerne wissen, was da genau vorgeht.
 
Zuletzt bearbeitet:
SimDatenListe.SimEintrag[SPS].DB_Maximum liefert die Bytes, die aus einem DB gelesen werden sollen + 1 Byte.
Warum + 1 Byte ?

Komisch ist auch das hier:
plc_amount := SimDatenListe.SimEintrag[SPS].DB_Maximum div 2; //ist für DB_read in prodave

Bei statischen Arrays hatte ich da die gleiche Länge wie die Array-Länge stehen und es ging. Nun gabs Fehler und ich mußte div 2 einfügen (rumprobiert). Damit werden aber trotzdem alle Bytes gelesen, auch die letzten! Ist doch irgendwie nicht ganz schlüssig.
Laut der Siemens-Doku zu Prodave, die ich so auf die Schnelle per Google gefunden habe, liest DB_read eine Anzahl von Datenworten, und damit wäre dann klar, wofür Du den div 2 brauchst. Wenn der Datenblock kürzer ist, liefert DB_read laut der gleichen Doku nur die vorhandenen Bytes und einen Fehlercode, das hat Dich vermutlich bei der Verwendung von statischen Arrays davor bewahrt, wild im Speicher rumzuschreiben ... :ROFLMAO:

Schreibt Prodave evtl. auch was rein in die zusätzlichen Bytes ? Wenn ja, was ?

Die Doku schweigt sich darüber leider aus, bezeichnend ist aber, daß in dem Beispielcode in der Doku zum Lesen von 45 Worten ein Puffer von 100 Worten verwendet wird ... :rolleyes:


Gruß Axel
 
@afk

Ja, die Prodave-Implementierung hab ich vor 3 Jahren oder so gemacht, da ist mir viel schon wieder entfallen. Eine Fehlermeldung hatte ich bei statischen Arrays nie, die Werte ich aus, allerdings verwende ich eine ältere Prodave-Mini-Version. Interessant in diesem Zusammenhang: Hat man den Step7-Manager installiert, reicht die Prodave-DLL und schon hat man Zugriff auf die SPS, Step7 bringt alles mit was benötigt wird, bis auf die DLL.

Ich werd mal einen Datenzugriff auf wenige Wörter machen und nachsehen, was ankommt, das wird aber erst morgen. Das plc_amount Wörter meint hatte ich auch vermutet, deshalb kam ich auf div 2. Also bei libnodave kann ich das +1 Byte weglassen, werd das mit prodave auch nochmal ausprobieren, vielleicht hab ich mir das Leben zu schwer gemacht. Ich schreib dann morgen mal das Ergebnis.
 
Zurück
Oben