Array flexibel in der Größe anlegen

Bensen83

Level-1
Beiträge
777
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich möchte einen FB ertsellen, welcher flexibel in einer Arraygröße sein soll.

Also dieser FB soll werte in ein Array speichern könn. Dabei kann es vorkommen, dass er ur mal 10 Werte speichern muss, oder auch mal 1000.

Gibt es eine möglichkeit das Array im code zu erzeugen, so dass ich nicht immer ein Array mit 1000 Elementen anlegen muss?
 
Zuviel Werbung?
-> Hier kostenlos registrieren

weil das Entwicklungs System bei einer SPS garantieren muss, dass der Fall, dass das Memory nicht reicht, nie eintritt.

Stell Dir vor, Du willst ein Array aus 1000.000 INT allocieren (normal nur 10 oder 1000), was soll dann die SPS machen? Anhalten, einfach nur das Maximum Mögliche hergeben oder dezent abstürzen?

Deshalb legt das System zusammen mit dem verwendeten Target beim Erstellen fest, ob es geht oder nicht und dazu braucht es eine exakte Grösse.
 
Was jedoch geht, sollte noch angemerkt werden:

VAR
myArray: ARRAY[1..myArraySize] OF BYTE;
END_VAR
VAR_CONSTANT
myArraySize:INT:=100;
END_VAR

Da Du nicht gesagt hast wann du die Flexibilität brauchst.
Während des Kompilierens ist es nämlich möglich.
Zur Laufzeit, wie meine Vorredner schon sagten, definitiv nicht.
 
Hier ein Beitrag aus einem anderen Thread, der vlt. helfen könnte, falls du wirklich dynamische Arrays hast:
Also wenn man die Array-Grösse ändert, MUSS immer neu kompiliert werden, das geht zur Laufzeit sicher nicht. Die Grösse muss als VAR_CONSTANT deklariert sein...

Ich mache oft 2 Variablen, eine die max. Grösse, die erlaubt ist (damit instanziere ich das Array) und eine Anzahl Werte (Also wieviel ich vom Instanzierten Array verwende)

Dies ist zwar Speicherfressend, aber man kann zur Laufzeit die nutzbare Array-Grösse anpassen...

P.S. Aus Erfahrung auch nie Online-Changes nach dem Ändern der Arraygrösse machen, das kann ein wunderbares Durcheinander im Speicher verursachen :grin:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn der FB flexibel sein soll und die Arraygröße vorm Übersetzen bekannt ist,
schau doch mal im Info Sys unter Pointer nach. Mit Hilfe des ADR und Sizeof Operators kannst du dann am Bausteineingang die Startadresse und Größe des Zielarrays ünergeben.
Im Baustein selbst kannst du dann per Pointer hochzählen und deine Daten in das Array schreiben.

Ich nutze diese Möglichkeit z.B. um mit einem FB Arrays aus CSV Dateien zu füllen.


Gruß
 
Doch! Zumindest mit TwinCAT3 /CoDeSys3!

PLC_PRG(PRG)
VAR
bInit: BOOL := TRUE;
bDelete: BOOL;
pArrayBytes : POINTER TO BYTE;
pArrayDuts : POINTER TO BYTE;

test: INT;

parr : POINTER TO BYTE;

END_VAR

IF (bInit) THEN

pArrayBytes := __NEW(BYTE, 25);

bInit := FALSE;

END_IF

IF (pArrayBytes <> 0) THEN

pArrayBytes[24] := 125;

test := pArrayBytes[24];

END_IF

IF (bDelete) THEN

__DELETE(pArrayBytes);

END_IF
 
Zuletzt bearbeitet:
Wer ist denn so mutig und setzt TwinCat 3 produktiv ein ?
Männer ohne Nerven gibt es immer, und die finden dann auch bestimmt eine Möglichkeit, dynamische Variablen in einem Automationsprogramm sinnvoll einzusetzen. Wie viele von denen wohl den Hinweis in der CoDeSys-Hilfe verstehen, dass die dynamische Speicherverwaltung nicht reentrant ist?
google mal nach "verkettete Liste", eine dynamische Datenstruktur
könnte dir vielleicht helfen
Das ist in CoDeSys schwierig. Der Knoten einer verketteten Liste würde ja etwa so aussehen:
Code:
TYPE strNode
STRUCT
   Prev:POINTER TO strNode;
   Next:POINTER TO strNode;
   Data:POINTER TO strData;
END_STRUCT
END_TYPE
CoDeSys erlaubt aber innerhalb eines Structs keinen Verweis auf den eigenen Typ. Da müsste man schon in der strNode mit einem "POINTER TO ARRAY[0..11] OF BYTE" arbeiten und dann immer in externe Variablen vom Typ "POINTER TO strNode" umkopieren. Wäre mir zu umständlich.
 
Jetzt muss ich dann doch mal meinen Senf dazu geben.


Alle Wunschträume von SPS Programmieren Arrays zur Laufzeit verändern zu können sind seit 30 oder mehr Jahren nicht in Erfüllung gegangen und werden es auch nicht.

Klar kann man Funktionen und/oder Funktionsblöcke so schreiben, dass Arrays früher terminieren als die maximale Länge, mit allerlei MIttel, Pointern, SizeOf, Exit etc. Tatsache bleibt, dass die Größe einer Datenstruktur vor dem Kompilieren angegeben werden muss und nicht veränderbar ist.


so und jetzt hol ich mir zu dem Senft a Wurscht.

;)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Die dynamische Speicherverwaltung hat erstmal nichts mit isochronen Takten zu tun. Nach dieser Argumentation würden ja dann auch keine Schleifen mit variabler Durchlauf-Zahl oder vorzeitigem Abbruch, keine Verschachtelung usw. usf. erlaubt sein ....

Das Problem mit der dynamischen Zuweisung von Speicher ist die Verwaltung des selbigen. Es muss 100% sicher gestellt werden, dass es keine Überläufe oder Überschneidungen gibt. Ersteres würde die SPS abstürzen lassen (höchstwahrscheinlich) und letzteres kann im Programm zu unerwarteten Zuständen führen die je nach Maschine teuer bis lebensgefährlich sein können.
Der Aufwand dieses bei größer werdenen Programmen zu überblicken steigt exponential und damit auch die Wahrscheinlichkeit eines kritischen Fehlers.

In C++ kann man mit einer unbedachten Speicherzuweisung den Rechner crashen. In .NET wird deswegen die Speicherverwaltung von der CLR übernommen, aber Garbage Collector & Co kosten dafür Performance.
 
Ok. Also besser nicht.

Also ich mag Pointer auch nicht so. Ist sicher Geschmacksache, aber gerade wenn man etwas flexibel halten will, sollte man ja vorsichtig mit Pointern sein.

Sicher ist sicher !!!
Und um einen Absturz zu vermeiden würde ich auch vorbeugend Pointer vermeiden.
Wer stimmt mir da zu?

Danke. ;-)
 
Zurück
Oben