Using Codesys v2.3, I'm trying to make a function block that checks the size of the pointer data, as to not write to parts of the memory beyond this.
Ex:
VAR_INPUT
pData: POINTER TO REAL; // Or pointer to WORD or ARRAY[1..x] ...
END_VAR
VAR_OUTPUT
DataSize: DWORD;
END_VAR
IF SIZEOF(pData^) <> 4 THEN
RETURN;
END_IF
DataSize := SIZEOF(pData^);
Now, if I were to put the adress of a BYTE into pData of this block, the IF would still check out, as the dereferenced pointer only seems to return the size of what we point at (REAL in this case).
I know it's possible to require the size as an input, but this could be a potential problem if it's missed or inputted wrong, as it would mess with the program in other ways
Is there a way to check the size of whatever data is pointed at, while avoiding external inputs?
As far as I know, there is no way to detect what is the datatype of the pointer, as it's just a memory address. You should provide the size of the pointer target as other parameter, as you said. Just add a check that pointer is not zero and size is not zero to prevent (some) problems.
Solutions for other environments:
For TwinCAT 3 it would be possible to create one-input solution by using T_Arg
and helpers suchs as F_INT
but I think Codesys 2 doesn't have them (confirmation anyone?). In that solution you would have to change the function call anyways so that pointer wouldn't be an input.
In that solution you could create a function with input of T_Arg
. And then call it by using a helper function for each datatype. From T_Arg
is possible to acquire data type, size and data location.
FUNCTION_BLOCK FB_Test
VAR_INPUT
Test : T_arg;
END_VAR
Test.eType; //Data type
Test.cbLen; //Variable data length in bytes
Test.pData; //Pointer to data
And to call it:
test is an instance of FB_Test
//INT for example
//Now the cblen = 2
test(
Test := F_INT(PointerToInt^)
);
//REAL for example
//Now the cbLen = 4
test(
Test := F_REAL(PointerToReal^)
);
This is perhaps a little offtopic so sorry about that, hope it helps somebody. Still hoping that somebody would know a better solution.
EDIT Actually found other great solution, but I think it is also only for TwinCAT 3. Just wanted to post it here too.
By using ANY
data type, it is possible to give anything as parameter and get it's size. The difference is that it won't accept POINTER
as input.
FUNCTION_BLOCK FB_Test2
VAR_INPUT
Test : ANY;
END_VAR
VAR_OUTPUT
Size : DINT;
END_VAR
//diSize contains size of the input data type
size := Test.diSize;
Usage:
//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
Test := PointerToReal^
);