Wie kann der Ergebniswert bei verschachtelten String-Bausteinen vollständig abgebildet werden?
Falls Sie Bausteine mit STRING-Werten ohne einer maximalen Länge (z.B. String-Bausteine) verschachtelt in der Anwendung verwenden, ist der zur Verfügung stehende Speicher dafür beschränkt. Diese Beschränkung ist abhängig vom verwendeten Zielsystem (siehe "Zielsystem-spezifische Eigenschaften und Einschränkungen"). In Folge ist es möglich, dass:
ein Ergebniswert nicht vollständig im zur Verfügung stehenden Speicher abgebildet werden kann
und
bei einem anderen Zielsystem ein unterschiedlich langer Ergebniswert entsteht.
Falls Sie beide Folgen vermeiden wollen, verwenden Sie Bausteine mit STRING-Werten ohne einer maximalen Länge nicht verschachtelt. Bei anwenderdefinierten Bausteinen können beide erwähnten Folgen nicht eintreten, da darin die STRING-Variablen mit einer maximalen Länge deklariert werden müssen.
Auch falls Sie die Bausteine nicht verschachtelt verwenden, ist es natürlich trotzdem möglich, dass der STRING-Ergebniswert nicht im zur Verfügung stehenden Speicher abgebildet werden kann. In diesem Fall wird übrigens der Ausgang ENO des Bausteins auf den Wert FALSE (oder eine Entsprechung) gesetzt (siehe auch Abschnitt "Interne Fehlerdiagnose für Baustein" in den Baustein-Beschreibungen, wie sich der Baustein verhält).
Die folgenden Beispiele mit dem CONCAT-Baustein geben Ihnen ein Überblick über mögliche Verwendungen und deren Folgen. Der CONCAT-Baustein wurde für die Beispiele ausgewählt, da er sowohl über Eingänge als auch über einen Ergebniswert vom Datentyp STRING ohne einer maximalen Länge verfügt. Die berechneten Werte werden mit Hilfe des Assert-Bausteins ausgewertet.
Beispiel 2: CONCAT ohne Verschachtelung, ENO=FALSE (da Ergebniswert zu lang)
Beispiel 3: CONCAT ohne Verschachtelung, ENO=TRUE – keine Beschränkung auf 1.024 Zeichen
Beachten Sie: Je größer ein STRING-Wert ist, desto mehr Arbeitsspeicher wird am Zielsystem benötigt. Falls kein ausreichender Arbeitsspeicher auf dem Zielsystem verfügbar ist, kann die Anwendung auf das Zielsystem wahrscheinlich gar nicht erfolgreich geladen werden.
Beispiel 1: CONCAT ohne Verschachtelung, ENO=TRUE
Der Ergebniswert wird vollständig abgebildet, da resultString1 mit einer Länge von 300 Zeichen deklariert ist. Das Verhalten auf unterschiedlichen Zielsystemen ist identisch, da CONCAT nicht verschachtelt benutzt wird (die Beschränkung des Speichers wird hier nicht angewendet).
FUNCTION_BLOCK ConcatSample1
VAR
resultString1 : STRING[
300
];
length1 : INT;
eno1 : BOOL;
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* The
3
inputs amount to
300
characters. This is OK because
'resultString1'
has a length of
300
characters. So
'eno1'
evaluates to
'TRUE'
. *)
resultString1 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>eno1);
length1 := LEN(resultString1);
ASSERT(length1=
300
);
ASSERT(eno1);
END_FUNCTION_BLOCK
Beispiel 2: CONCAT ohne Verschachtelung, ENO=FALSE (da Ergebniswert zu lang)
Der Ergebniswert wird nicht vollständig abgebildet, da resultString2 mit einer Länge von 200 Zeichen deklariert ist. Das Verhalten auf unterschiedlichen Zielsystemen ist aber identisch, da CONCAT nicht verschachtelt benutzt wird (die Beschränkung des Speichers wird hier nicht angewendet).
FUNCTION_BLOCK ConcatSample2
VAR
resultString2 : STRING[
200
];
length2 : INT;
eno2 : BOOL;
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* The
3
inputs amount to
300
characters. But
'resultString2'
has a length of
200
characters. So
'eno2'
evaluates to
'FALSE'
. *)
resultString2 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>eno2);
length2 := LEN(resultString2);
ASSERT(length2=
200
);
ASSERT(NOT eno2);
END_FUNCTION_BLOCK
Beispiel 4: CONCAT mit Verschachtelung, ENO einiger inneren CONCATs=FALSE – Beschränkung auf 1.024 Zeichen
Der zusammengesetzte Ergebniswert wird nicht vollständig abgebildet, obwohl resultString4 mit einer Länge von 1.500 Zeichen deklariert ist. Das Verhalten auf unterschiedlichen Zielsystemen ist nicht identisch, da CONCAT verschachtelt benutzt wird. Somit wird hier die Beschränkung des Speichers angewendet – beim Laufzeitsystem für Windows ist dies 1.024 Bytes, wobei 1 Byte von diesem Speicher pro CONCAT-Aufruf außerdem für interne Zwecke verwendet wird. Falls eine andere Beschränkung für das Zielsystem gilt (z.B. für Controllinos), entsteht ein anderer Ergebniswert.
FUNCTION_BLOCK ConcatSample4
VAR
resultString4a : STRING[
1500
];
length4a : INT;
eno4a, enoA1, enoB1, enoC1, enoD1 : BOOL;
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* Here there is a nested usage of CONCAT. The scenario is as follows:
Unsized strings are assigned to
4
inputs of the outer CONCAT by calling CONCAT blocks again. Let's call them the inner CONCATs.
A string with a length of
100
characters is assigned to the
3
inputs of each inner CONCAT. For runtime system
for
Windows,
this
is valid:
* The
3
inputs of the 1st inner CONCAT amount to
300
characters.
1
byte
of the memory is used
for
internal purpose. As
301
<
1024
,
'enoA1'
evaluates to
'TRUE'
.
300
characters can be mapped in the available memory.
* The
3
inputs of the 2nd inner CONCAT ampunt to
300
characters as well.
1
byte
of the memory is again used
for
internal purpose. As
602
<
1024
,
'enoB1'
evaluates to
'TRUE'
.
300
characters can be mapped in the available memory.
* The
3
inputs of the 3rd inner CONCAT amount to
300
characters as well.
1
byte
of the memory is again used
for
internal purpose. As
903
<
1024
,
'enoC1'
evaluates to
'TRUE'
.
300
characters can be mapped in the available memory.
* The
3
inputs of the 4th inner CONCAT amount to
300
characters as well.
1
byte
of the memory is again used
for
internal purpose. As
1204
>
1024
,
'enoD1'
evaluates to
'FALSE'
. Only
120
characters (of the
300
characters) can be mapped in the available memory.
So a string of
1020
characters is assigned to the outer CONCAT (
300
+
300
+
300
+
120
). This is OK because
'resultString4a'
has a length of
1500
characters. So
'eno4a'
evaluates to
'TRUE'
. *)
resultString4a := CONCAT(IN1 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoA1), IN2 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoB1), IN3 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoC1), IN4 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoD1), ENO=>eno4a);
length4a := LEN(resultString4a);
ASSERT(length4a=
1020
); (* Valid
for
: runtime system
for
Windows. In
case
of a Controllino Maxi Automation,
'resultString4a'
would just have a length of
63
characters. *)
ASSERT(eno4a);
ASSERT(enoA1); (* Valid
for
: runtime system
for
Windows. In
case
of a Controllino Maxi Automation,
'enoA1'
to
'enoD1'
would evaluate to
'FALSE'
. *)
ASSERT(enoB1);
ASSERT(enoC1);
ASSERT(NOT enoD1);
END_FUNCTION_BLOCK
Beispiel 5: Analog zu Beispiel 4, aber ohne Verschachtelung und alle ENO=TRUE – keine Beschränkung auf 1.024 Zeichen
Der Ergebniswert wird vollständig abgebildet, da resultString5 mit einer Länge von 3.000 Zeichen deklariert ist. Das Verhalten auf unterschiedlichen Zielsystemen ist identisch, da CONCAT nicht verschachtelt benutzt wird. Auch hier wird die Beschränkung des Speichers nicht angewendet. Dies ist daran erkennbar, dass der Ergebniswert von 1.200 Zeichen vollständig abgebildet wird (eigentlich würde er die Grenze von 1.024 Bytes beim Laufzeitsystem für Windows überschreiten).
FUNCTION_BLOCK ConcatSample5
VAR
resultString5 : STRING[
1500
];
length5 : INT;
eno5, enoV1, enoV2, enoV3, enoV4 : BOOL;
VarString1, VarString2, VarString3, VarString4 : STRING[
300
];
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* Here a workaround to avoid the restriction of
1024
bytes. Assign the result of the previously
"inner"
CONCAT blocks to STRING variables. Here all ENOs evaluate to
'TRUE'
. *)
VarString1 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoV1);
VarString2 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoV2);
VarString3 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoV3);
VarString4 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoV4);
(* Then assign these STRING variables to the inputs of the previously
"outer"
CONCAT. This makes the code easier to read as well. *)
resultString5 := CONCAT(IN1 := VarString1, IN2 := VarString2, IN3 := VarString3, IN4 := VarString4, ENO=>eno5);
length5 := LEN(resultString5);
ASSERT(length5=
1200
);
ASSERT(eno5);
ASSERT(enoV1);
ASSERT(enoV2);
ASSERT(enoV3);
ASSERT(enoV4);
END_FUNCTION_BLOCK