Search code examples
pointerssizeofcodesys

CoDeSys size of pointer reference


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?


Solution

  • 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_Argand 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^
    );