c指针减少安全/不安全?

时间:2018-02-19 11:04:10

标签: c pointers unsafe-pointers

分析一些代码:

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)已用于其他变量并覆盖它可能会导致故障。

您如何看待,这样的代码是可以使用还是错误的方式,永远不应该使用?

4 个答案:

答案 0 :(得分:7)

从此评论中

    /* First byte before the Modbus-PDU is the slave address. */
    pucSndBufferCur = ( UCHAR * ) pucFrame - 1;

我们可能会推断该函数希望调用者保证这一点。在这种情况下,如果调用者满足要求,则然后代码是安全的。

如果来电者保证这一点,则该功能安全。这就像您无法有效检查的任何其他先决条件一样:如果违反了要求,它们会有UB,而这是来电者的错误

为了进行比较,free()如果违反了从malloc()/realloc()返回其指针参数的先决条件,则可能会有类似的行为(可能会出现更糟糕的副作用)。

  

看起来不安全,如果地址中的内存(pucFrame - 1)已用于其他变量并覆盖它可能会导致故障

不安全 - 它是C.正确使用它的责任是你的。如果你错误地使用它(传递一个不符合规定要求的指针),就会出现故障并且它们将是你的错。

  

您如何看待,这样的代码是可以使用还是错误的方式,永远不应该使用?

它可以安全使用,就像free()可以安全使用一样。它可以以错误的方式使用,因为free()可能被滥用。 从不使用这样的代码的唯一原因是你不相信自己正确使用它。

实际的建议是查看这个pucFrame指针的来源,验证它始终保证满足要​​求,然后确保在指针的代码行程中不会破坏任何内容。

答案 1 :(得分:1)

语句pucSndBufferCur = ( UCHAR * ) pucFrame - 1;的行为将是 undefined ,除非pucFrame是指向数组中元素的指针,或者只是在数组结束之后,并且是它之前的一个元素。为此,可以将标量视为长度为1的数组。

这是因为指针算法仅在数组中有效。

你也丢弃了const,它可以再次将程序置于未定义的状态,这取决于你对指针的处理方式(以及C和C ++之间的规则不同)。

答案 2 :(得分:1)

永远不要假设某个地址位于特定地址之前或之后,除非您正在检查数组范围内的某些内容。

MISRA-C:2004,规则17.4(必填)或MISRA-C:2012,规则18.4(必填)数组索引应是唯一允许的指针算术形式。

强烈建议您使用像PC-Lint这样的静态分析器来检查代码的健全性,以避免未定义的行为。

此外,您可以将所有必需的东西放入结构中,只需将结构指针传递给函数即可。但即使这样,也不要使用++或 - 来访问struct成员,因为你不知道添加的填充是依赖于编译器的

答案 3 :(得分:0)

请清除问题的感觉。 无论如何代码有点不安全,但不是你告诉的原因。 为了使其更强大,您应该测试null。 指针算法有点危险,但我认为这个OLD代码会根据上下文做出一些假设。

它似乎来自:

FreeModbus Libary:Modbus ASCII / RTU的便携式Modbus实现。 3 *版权所有(c)2006 Christian Walter

所以是的,2006年的代码可能很危险,但另一方面它已经使用了15年......所以可以使用它。 (旧代码通常有效但如果你不修改它。)