指针引用的 CoDeSys 大小

CoDeSys size of pointer reference

使用 Codesys v2.3,我正在尝试制作一个功能块来检查指针数据的大小,以免写入超出此范围的内存部分。
例如:

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

现在,如果我将 BYTE 的地址放入此块的 pData 中,IF 仍会检查,因为解除引用的指针似乎 return 我们指向的大小(在这种情况下是真实的)。

我知道可以要求将大小作为输入,但如果遗漏或输入错误,这可能是一个潜在的问题,因为它会以其他方式扰乱程序

有没有办法检查指向的任何数据的大小,同时避免外部输入?

据我所知,无法检测指针的数据类型是什么,因为它只是一个内存地址。如您所说,您应该提供指针目标的大小作为其他参数。只需添加一个检查指针不为零且大小不为零以防止(某些)问题。


其他环境的解决方案:


对于 TwinCAT 3,可以通过使用 T_ArgF_INT 等助手来创建单输入解决方案,但我认为 Codesys 2 没有它们(有人确认过吗?)。在该解决方案中,您无论如何都必须更改函数调用,这样指针就不会成为输入。

在该解决方案中,您可以创建一个输入为 T_Arg 的函数。然后通过为每种数据类型使用辅助函数来调用它。从T_Arg可以获取数据类型、大小和数据位置。

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

并调用它:

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

这可能有点跑题了,对此深表歉意,希望对大家有所帮助。仍然希望有人知道更好的解决方案。

编辑 实际上找到了其他很好的解决方案,但我认为它也只适用于 TwinCAT 3。只是想 post 也在这里。

通过使用 ANY 数据类型,可以将任何东西作为参数并获取它的大小。区别在于它不会接受 POINTER 作为输入。

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;

用法:

//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
    Test := PointerToReal^
);

为什么你需要这样一个函数,只是为了检测变量大小,而这个函数已经存在了?

您所要做的就是直接在您的程序中调用 SIZEOF()。您不需要使用指针。据我了解,您使用它们是因为您想让输入变量成为任何类型的通用变量,而不是因为您在程序中使用了指针。所以原来的变量都是直接分配的

您的函数试图在不更改计算算法的情况下围绕 SIZEOF() 创建环绕,然后只需使用 SIZEOF(),因为这就是此函数的用途。

告诉我你为什么要尝试创建单独的函数,而我 我会相应地更改答案。

我假设您需要检查变量的大小是否是您需要的。然后就可以做一个函数了。

FUNCTION IsSize : BOOL
    VAR_INPUT
        VarSize: INT;
        CompareTo: INT;
    END_VAR
    IsSize := (VarSize = CompareTo);
END_FUNCTION

然后你可以这样称呼它

VAR
    MyVar: REAL;
END_VAR

IF IsSize(SIZEOF(MyVAR), 4) THEN
    // DO something
END_IF

编辑:使用数组

如果您想创建一个与数组一起使用的函数,并且您希望能够传递无限数量的元素数组,那么您可以这样做。

FUNCTION ArrSize : BOOL
    VAR_INPUT
        MyArr: POINTER TO ARRAY[0..1000] OF BOOL;
        ArrNum: INT; (* Number of array elements *)
        ArrStart: INT; (* First index of an array *)
    END_VAR
    VAR
        iCount : INT := 0;
    END_VAR

    FOR iCount := ArrStart TO ArrNum DO
        MyArr^[iCount] := TRUE;
    END_FOR
END_FUNCTION

然后在代码中你可以

VAR
    aTest: ARRAY[0..20] OF BOOL;
END_VAR

ArrSize(ADR(aTest), SIZEOF(aTest), 0);