c指针递减safe/unsafe?
c pointer decrement safe/unsafe?
正在分析一些代码:
static volatile UCHAR *pucSndBufferCur;
eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
{
if( eRcvState == STATE_RX_IDLE )
{
/* First byte before the Modbus-PDU is the slave address. */
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
pucSndBufferCur[0] = ucSlaveAddress;
看起来不安全,如果地址(pucFrame - 1)中的内存已经被其他变量使用并且覆盖它可能会导致故障怎么办。
您怎么看,这样的代码可以使用还是错误的方式永远不应该使用?
语句 pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
的行为将是 undefined 除非 pucFrame
是一个指向数组中元素的指针,或者就在数组,并且它前面有一个元素。为此,标量可以被视为长度为 1 的数组。
这是因为指针算法只在数组中有效。
您也放弃了 const
,这可能会再次将程序置于未定义状态,具体取决于您对指针所做的操作(C 和 C++ 之间的规则不同)。
请澄清您问题的意义。
无论如何,代码有点不安全,但不是因为你所说的原因。
为了使其更健壮,您应该针对 null 进行测试。
指针运算有点危险,但我认为这段旧代码会根据上下文做出一些假设。
它似乎来自:
FreeModbus 库:Modbus ASCII/RTU 的可移植 Modbus 实现。
3 * 版权所有 (c) 2006 Christian Walter
所以是的,2006 年的代码可能很危险,但另一方面它已经使用了 15 年......所以它可以使用。 (旧代码通常可以工作,但如果你不修改它..)
来自这条评论
/* First byte before the Modbus-PDU is the slave address. */
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
我们可能会推断该函数希望调用者保证这一点。在这种情况下,if 调用者满足要求,then 代码是安全的。
如果调用者不保证这一点,则函数不安全。这就像您无法有效检查的任何其他 pre-requisite:如果违反要求,他们就会有 UB,这是调用者的错。
作为比较,如果您违反 pre-requisite 其指针参数是从 malloc()/realloc()
返回的,free()
可能会有类似的行为(并且可能更糟 side-effects)。
It looks like unsafe, what if memory in address (pucFrame - 1 ) is already used for other variable and overwriting it could cause malfunctions
它 不安全 - 它是 C。正确使用它的责任在你。如果你用错了(传递了一个不符合规定要求的指针),就会出现故障,那就是你的错。
What do you think, is code like this can be used or its wrong way and never should be used ?
可以放心使用,就像free()
可以放心使用一样。它可以被错误地使用,就像 free()
可以被误用一样。 从不 使用这样的代码的唯一原因是您不相信自己会正确使用它。
实用的建议是查看这个 pucFrame
指针的来源,验证它始终保证满足要求,然后确保在指针通过您的过程中没有破坏任何东西代码。
永远不要假设某些东西位于特定地址之前或之后,除非您正在检查数组范围内的东西。
MISRA-C:2004,规则 17.4(必需)或 MISRA-C:2012,规则 18.4(必需)数组索引应是指针运算的唯一允许形式。
强烈建议您使用像 PC-Lint 这样的静态分析器来检查代码的完整性,以避免未定义的行为。
此外,您可以将所有必需的东西放入一个结构中,然后将一个结构指针传递给该函数。但即便如此,也不要使用 ++ 或 -- 访问结构成员,因为你不知道添加的填充是依赖于编译器的
正在分析一些代码:
static volatile UCHAR *pucSndBufferCur;
eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
{
if( eRcvState == STATE_RX_IDLE )
{
/* First byte before the Modbus-PDU is the slave address. */
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
pucSndBufferCur[0] = ucSlaveAddress;
看起来不安全,如果地址(pucFrame - 1)中的内存已经被其他变量使用并且覆盖它可能会导致故障怎么办。
您怎么看,这样的代码可以使用还是错误的方式永远不应该使用?
语句 pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
的行为将是 undefined 除非 pucFrame
是一个指向数组中元素的指针,或者就在数组,并且它前面有一个元素。为此,标量可以被视为长度为 1 的数组。
这是因为指针算法只在数组中有效。
您也放弃了 const
,这可能会再次将程序置于未定义状态,具体取决于您对指针所做的操作(C 和 C++ 之间的规则不同)。
请澄清您问题的意义。 无论如何,代码有点不安全,但不是因为你所说的原因。 为了使其更健壮,您应该针对 null 进行测试。 指针运算有点危险,但我认为这段旧代码会根据上下文做出一些假设。
它似乎来自:
FreeModbus 库:Modbus ASCII/RTU 的可移植 Modbus 实现。 3 * 版权所有 (c) 2006 Christian Walter
所以是的,2006 年的代码可能很危险,但另一方面它已经使用了 15 年......所以它可以使用。 (旧代码通常可以工作,但如果你不修改它..)
来自这条评论
/* First byte before the Modbus-PDU is the slave address. */
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
我们可能会推断该函数希望调用者保证这一点。在这种情况下,if 调用者满足要求,then 代码是安全的。
如果调用者不保证这一点,则函数不安全。这就像您无法有效检查的任何其他 pre-requisite:如果违反要求,他们就会有 UB,这是调用者的错。
作为比较,如果您违反 pre-requisite 其指针参数是从 malloc()/realloc()
返回的,free()
可能会有类似的行为(并且可能更糟 side-effects)。
It looks like unsafe, what if memory in address (pucFrame - 1 ) is already used for other variable and overwriting it could cause malfunctions
它 不安全 - 它是 C。正确使用它的责任在你。如果你用错了(传递了一个不符合规定要求的指针),就会出现故障,那就是你的错。
What do you think, is code like this can be used or its wrong way and never should be used ?
可以放心使用,就像free()
可以放心使用一样。它可以被错误地使用,就像 free()
可以被误用一样。 从不 使用这样的代码的唯一原因是您不相信自己会正确使用它。
实用的建议是查看这个 pucFrame
指针的来源,验证它始终保证满足要求,然后确保在指针通过您的过程中没有破坏任何东西代码。
永远不要假设某些东西位于特定地址之前或之后,除非您正在检查数组范围内的东西。
MISRA-C:2004,规则 17.4(必需)或 MISRA-C:2012,规则 18.4(必需)数组索引应是指针运算的唯一允许形式。
强烈建议您使用像 PC-Lint 这样的静态分析器来检查代码的完整性,以避免未定义的行为。
此外,您可以将所有必需的东西放入一个结构中,然后将一个结构指针传递给该函数。但即便如此,也不要使用 ++ 或 -- 访问结构成员,因为你不知道添加的填充是依赖于编译器的