【问题标题】:Last value assigned to variable not used [MISRA 2012 Rule 2.2, required]分配给变量的最后一个值未使用 [MISRA 2012 规则 2.2,必需]
【发布时间】:2021-08-06 13:19:48
【问题描述】:

我在使用如下代码时收到此警告:

//Macro
#define FREEIF(p)            if (p) { free_mem((void*)p); (p) = 0; }

//free_mem function
int free_mem(void *mem_ptr)
{
    if (mem_ptr != NULL)
    {
        free(mem_ptr);
    }
    mem_ptr = NULL;
    return 0;
}


//Use of Macro in my .c file with above declaration and definition of macro.
....
....

{
 FREEIF(temp_ptr);
}

如果我在调用 MACRO 之前添加对“temp_ptr”的检查,例如 if (temp_ptr) {FREEIF(temp_ptr);},我不会收到此警告。

因为我已经检查了 MACRO 中的“temp_ptr”。我想知道为什么会收到此警告。

有什么见解吗?

【问题讨论】:

  • 仅供参考,您无需检查传递给free() 的内容是否为NULL,因为free(NULL); 被定义为什么都不做。
  • 在离开函数之前将NULL 分配给free_mem 内部的指针没有任何价值,无论如何,该变量都会超出范围。如果您传递双指针 (void** ptr) 并将 NULL 分配给 *ptr,情况会发生变化。
  • 您可以尝试#define FREE(p) do { free(p); (p) = NULL; (void)(p); } while(0) 并完全跳过free_mem...
  • 您在问题中没有明确说明消息指的是哪一行。您的代码包含两个将/可以触发此警告的地方。 FREEIF(temp_ptr); 的扩展包含temp_ptr = 0;。也许您的代码在分配后没有使用temp_ptr 的值。函数free_mem 包含对函数参数mem_ptr 中指针本地副本的赋值,该函数之后不使用也不传递给调用函数,所以这个赋值没有用。
  • 就像我上面提到的,警告出现在 .c 文件的行上。当我调用 FREEIF(temp_ptr);

标签: c macros misra


【解决方案1】:

关于错误,规则 2.2 是关于你的程序中没有任何“死代码”。

在函数中,mem_ptr = NULL;局部变量 mem_ptr 设置为 null,而不是传递的那个。所以该代码行什么都不做。这是错误的原因,也是常见的初学者常见问题解答,详情请参阅Dynamic memory access only works inside function

在类似函数的宏中,传递的指针会被(p) = 0; 改变。但是,如果在将指针设置为 null 后不使用指针,它仍然被视为“死代码”,因为严格来说,赋值是没有意义的(尽管是很好的做法)。我们无法确定,因为您没有发布调用代码,也没有发布实际的指针声明。

但这里有一些更严重的全局问题:

  • 同时使用 MISRA-C 和动态内存分配是没有意义的。它们几乎是相互排斥的。嵌入式系统一般不使用动态分配,尤其是裸机/RTOS MCU 应用,它simply doesn't make any sense

    在关键任务/安全相关软件中特别禁止动态分配。这不仅被 MISRA 禁止,而且被任何编码标准禁止。它也被 IEC 61508、ISO 26262、DO 178 等通用安全标准所禁止。

  • 抛开安全和 MISRA 不谈,您的宏仍然是无稽之谈,因为空指针上的 free() 是定义明确的空操作。参见 C17 7.22.3.3 中free 的定义:

    void free(void *ptr); /--/ 如果ptr为空指针,则不执行任何操作。

    因此,宏所实现的全部目的就是混淆代码,并通过一个额外的、毫无意义的分支来减慢它的速度。

这里正确的解决方案是核对这个宏,然后退后一步,考虑一下你对这个项目所做的事情。从需求开始。为什么需要 MISRA-C,这个项目中的某个人是否知道他们在做什么,如果不知道 - 我们应该聘请谁来帮助这个项目。等等。团队中至少需要一名 C 资深人士来完成 MISRA-C 项目,否则该项目注定失败。

【讨论】:

  • 嗨 Lundin,我明白了你的意思,但这并不能回答我的问题。为什么我会收到此错误?我分享的那段代码有什么问题。
  • @user3860869 很公平,我稍微扩展了答案。
【解决方案2】:

C 中的参数按值传递。这意味着作为参数传递的值将复制到函数内部可见的参数中,并且从函数中修改参数对传递的原始值没有任何影响。

因此,mem_ptr = NULL; 行毫无意义(至少假设没有未定义的行为,如越界读取或取消引用无效的指针,这似乎毫无意义),因为mem_ptr 是函数本地的,并且值未被读取任务结束后。

另一方面,(p) = 0; 可能不是没有意义的,因为p 没有在宏中声明,所以它会引用在宏之前声明的内容,并且可以在调用宏之后读取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多