0

使用 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 仍然会检查,因为取消引用的指针似乎只返回我们指向的大小(在这种情况下为 REAL)。

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

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

4

2 回答 2

1

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


其他环境的解决方案:


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

在该解决方案中,您可以创建一个输入为T_Arg. 然后通过对每个数据类型使用辅助函数来调用它。FromT_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。只是想在这里发布它。

通过使用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^
);
于 2018-07-03T13:14:24.667 回答
0

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

您所要做的就是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);
于 2018-07-04T04:58:55.613 回答