In case of nested string blocks: How can the return value be entirely mapped ?
If you are using nested blocks with STRING values without a maximum length (e.g. string blocks) within the application, the available memory is restricted. This restriction depends on the used target system (see "Properties and restrictions specific to the target system"). Subsequently, it is possible that:
a return value cannot be completely mapped in the available memory
and
a return value of a different length is created when a different target system is used.
If you want to avoid both consequences, do not nest blocks with STRING values without a maximum length. In case of user-defined blocks, both consequences cannot occur because the STRING variables must be declared with a maximum length.
Even if you do not nest the blocks, it is possible anyway that the STRING return value cannot be mapped in the available memory. In this case, the output ENO of the block is set to value FALSE (or an equivalent) (see also section "Internal error diagnostic for block" in the block descriptions how the block behaves).
The following examples calling the CONCAT block provide a better understanding of the possible usages and their consequences. The CONCAT block has been selected for the examples because this block has inputs as well as a return value of data type STRING without a maximum length. The calculated values are evaluated by using the Assert block .
Example 2: CONCAT without nesting, ENO=FALSE (because return value is too long)
Example 3: CONCAT without nesting, ENO=TRUE – no restriction to 1,024 characters
Example 4: CONCAT with nesting, ENO of some inner CONCATs=FALSE – restriction to 1,024 characters
Observe: The larger a STRING value is, the more RAM is required on the target system. If there is not sufficient RAM on the target system, it is likely that the application cannot be successfully loaded onto the target system at all.
Example 1: CONCAT without nesting, ENO=TRUE
The return value is completely mapped because resultString1 is declared with a length of 300 characters. The behavior on different target systems is identical because CONCAT is not nested (the restriction of the memory is not applied).
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
Example 2: CONCAT without nesting, ENO=FALSE (because return value is too long)
The return value is not completely mapped because resultString2 is declared with a length of 200 characters. However, the behavior on different target systems is identical because CONCAT is not nested (the restriction of the memory is not applied).
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
Example 3: CONCAT without nesting, ENO=TRUE – no restriction to 1,024 characters
The return value is completely mapped because resultString3 is declared with a length of 1,500 characters. The behavior on different target systems is identical because CONCAT is not nested. Here, the restriction of the memory is not applied as well. This becomes obvious as the return value of 1,100 characters can be mapped completely (actually, it would exceed the limit of 1,024 bytes that is valid when using the runtime system for Windows).
FUNCTION_BLOCK ConcatSample3
VAR
resultString3 : STRING[
1500
];
length3 : INT;
eno3 : BOOL;
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* The
11
inputs amount to
1100
characters. This is OK again because
'resultString3'
has a length of
1500
characters. So
'eno3'
evaluates to
'TRUE'
. *)
resultString3 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, IN4 := stringLength100, IN5 := stringLength100, IN6 := stringLength100, IN7 := stringLength100, IN8 := stringLength100, IN9 := stringLength100, IN10 := stringLength100, IN11 := stringLength100, ENO=>eno3);
length3 := LEN(resultString3);
ASSERT(length3=
1100
);
ASSERT(eno3);
END_FUNCTION_BLOCK
Example 4: CONCAT with nesting, ENO of some inner CONCATs=FALSE – restriction to 1,024 characters
The combined return value is not completely mapped although resultString4 is declared with a length of 1,500 characters. The behavior on different target systems is not identical because CONCAT is nested. Hence, the restriction of the memory is applied – this is 1,024 bytes when using the runtime system for Windows. Observe that 1 byte of the memory is used for each CONCAT call for internal purpose. If there is a different restriction for the target system (e.g. for Controllinos), a different value is returned.
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 the 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,
'resultString4a'
would just have a length of
63
characters. *)
ASSERT(eno4a);
ASSERT(enoA1);
ASSERT(enoB1);
ASSERT(enoC1);
ASSERT(NOT enoD1);
END_FUNCTION_BLOCK
Example 6: Example 4 enhanced by one inner CONCAT, ENO of some inner CONCATs=FALSE – restriction to 1,024 characters
The combined return value is also not completely mapped although resultString6 is declared with a length of 1,500 characters. The behavior on different target systems is not identical because CONCAT is nested. Hence, the restriction of the memory is applied – this is 1,024 bytes when using the runtime system for Windows. Observe that 1 byte of the memory is used for each CONCAT call for internal purpose. If there is a different restriction for the target system (e.g. for Controllinos), a different value is returned.
FUNCTION_BLOCK ConcatSample6
VAR
resultString6 : STRING[
1500
];
length6 : INT;
eno6, enoA2, enoB2, enoC2, enoD2, enoE2: BOOL;
stringLength100 : STRING[
100
] :=
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789'
;
END_VAR
(* This is identical to example
4
, but a 5th inner CONCAT is added. In addition to the behavior of example
4
, the
300
characters of the 5th inner CONCAT cannot be mapped at all because there is no available memory left. So
'enoE2'
evaluates to
'FALSE'
(such as
'enoD2'
). *)
resultString6 := CONCAT(IN1 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoA2), IN2 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoB2), IN3 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoC2), IN4 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoD2), IN5 := CONCAT(IN1 := stringLength100, IN2 := stringLength100, IN3 := stringLength100, ENO=>enoE2), ENO=>eno6);
length6 := LEN(resultString6);
ASSERT(length6=
1020
); (* Valid
for
: runtime system
for
Windows. In
case
of a Controllino Maxi Automation,
'resultString6'
would just have a length of
63
characters. *)
ASSERT(eno6);
ASSERT(enoA2); (* Valid
for
: runtime system
for
Windows. In
case
of a Controllino Maxi Automation,
'enoA2'
to
'enoD2'
would evaluate to
'FALSE'
. *)
ASSERT(enoB2);
ASSERT(enoC2);
ASSERT(NOT enoD2);
ASSERT(NOT enoE2);
END_FUNCTION_BLOCK