Pointers CoDeSys指针引用的大小
使用Codesys v2.3,我试图创建一个功能块,用于检查指针数据的大小,以避免写入超出此范围的部分内存。Pointers CoDeSys指针引用的大小,pointers,sizeof,codesys,Pointers,Sizeof,Codesys,使用Codesys v2.3,我试图创建一个功能块,用于检查指针数据的大小,以避免写入超出此范围的部分内存。 例: 如果SIZEOF(pData^)4那么 回来 结束(如有) 数据大小:=SIZEOF(pData^); 现在,如果我将一个字节的地址放入这个块的pData中,if仍然会检查出来,因为解引用指针似乎只返回我们所指向的大小(在本例中为实) 我知道可能需要输入大小,但如果丢失或输入错误,这可能是一个潜在问题,因为它会以其他方式干扰程序 有没有办法在避免外部输入的同时检查所指向数据的大
例:
如果SIZEOF(pData^)4那么
回来
结束(如有)
数据大小:=SIZEOF(pData^);
现在,如果我将一个字节的地址放入这个块的pData中,if仍然会检查出来,因为解引用指针似乎只返回我们所指向的大小(在本例中为实)
我知道可能需要输入大小,但如果丢失或输入错误,这可能是一个潜在问题,因为它会以其他方式干扰程序
有没有办法在避免外部输入的同时检查所指向数据的大小?据我所知,无法检测指针的数据类型,因为它只是一个内存地址。正如您所说,您应该提供指针目标的大小作为其他参数。只需添加一个指针不为零和大小不为零的检查,以防止(某些)问题
其他环境的解决方案:
对于TwinCAT 3,可以通过使用
T_Arg
和F_INT
等辅助工具创建一个输入解决方案,但我认为Codesys 2没有(有人确认吗?)。在该解决方案中,您必须无论如何更改函数调用,以便指针不会成为输入
在该解决方案中,您可以创建一个输入为T_Arg
的函数。然后对每个数据类型使用一个helper函数来调用它。从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^)
);
这可能有点离题了,所以很抱歉,希望它能帮助别人。仍然希望有人知道更好的解决办法
编辑
实际上找到了另一个很好的解决方案,但我认为它也只适用于Twincat3。我也想把它贴在这里
通过使用ANY
数据类型,可以将任何内容作为参数,并获取其大小。区别在于它不接受指针
作为输入
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()
,因为这就是该函数的用途
告诉我为什么要创建单独的函数和
I’我会相应地修改答案
我的假设是,您需要检查变量是否是您需要的大小。然后你可以做一个函数
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);
首先,它不应该是一个功能块,而是一个函数。其次,我们讨论的是CoDeSys 2.3,它不支持
ANY
或ANY_NUM
数据类型。至少我的实例没有。第三,变量不是ST中的对象,您不能对输入变量进行Test.diSize
,除非它是带有属性diSize
的结构Test
。Jabbi要求一个功能块,这就是为什么它是一个。在运行时调试函数块比调试函数更容易。但是是的,这应该是一个函数。我还提到,我认为Codesys 2.3不支持它,在匆忙发表评论之前,您是否阅读了我的回答?第三点:ANY
被转换成一个结构,因此Test.diSize
就像一个结构一样工作。兄弟,冷静点,我只是在分享我的经验。我不是在编辑或删除你的答案。说说我的想法。很抱歉,我的评论中有一些批评。但它不是愤怒和仇恨中的批评家。这是建设性的批评。你可以说“谢谢你,Sergey,你的宝贵意见”,而不是进入防守位置。遗憾的是,CoDeSys 2中没有这样的选项,拥有它真的很好。正如Sergey在评论中提到的,“DataSize:=SIZEOF(pData^);”应该被其他代码替换,我意识到这是一个糟糕的例子。我的想法是制作一个函数/块,它可以检测传入数据的大小,并相应地执行操作。它主要被认为是制作一个具有可变数组输入的函数块的一种方法,以便单个函数块可以处理多个情况。我问题中的例子就是,一个例子。这并不是我所理解的全部。我正在更改答案并添加答案。
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);