while循环Polyspace可能存在运行时错误

时间:2018-04-17 06:21:07

标签: memory embedded runtime-error dynamic-analysis

我正在使用嵌入式C语言,最近为整个项目运行MathWorks Polyspace Code Prover(动态分析),以检查关键的运行时错误。它在While循环中发现了一个错误(红色警告),我通过内存寄存器将一些ROM数据复制到RAM中。 代码工作正常并且符合预期,但我想问一下是否有任何解决方案可以安全地删除此警告。请在下面找到代码示例:

register int32 const *source;
uint32 i=0;
uint32 *dest;
source= (int32*)&ADDR_SWR4_BEGIN;
dest = (uint32*)&ADDR_ARAM_BEGIN;

    if ( source != NULL )
    {
        while ( i < 2048 )
        {
            dest[i] = (uint32)source[i];
            i++;
        }
     }

我的猜测是ADDR_SWR4_BEGIN和ADDR_ARAM_BEGIN是在链接描述文件中定义的,而polyspace没有编译和链接项目,这就是它抱怨可能的运行时错误或无限循环的原因。

ADDR_SWR4_BEGIN和ADDR_ARAM_BEGIN在相应的头文件中定义为extern。

extern uint32_t ADDR_SWR4_BEGIN;
extern uint32_t ADDR_ARAM_BEGIN;

警告为红色,确切警告如下:

Check:    Non-terminating Loop
Detail:   The Loop is infinite or contains a run-time error
Severity: Unset

任何建议都将不胜感激。

3 个答案:

答案 0 :(得分:1)

整个代码非常可疑。

<强>错误

  • if ( source != NULL )。您只需将此指针设置为指向一个地址,因此它显然不会指向NULL。这条线是多余的。
  • 访问寄存器/内存时,您没有使用volatile,因此如果多次执行此代码,编译器可能会做出各种奇怪的假设。这可能是诊断消息的原因。

风格/代码异味(应该修复)

  • 使用register关键字很可疑。这曾经是20世纪80年代的一个问题,当时编译器非常糟糕,无法正确优化代码。现在他们可以做到这一点,并且比程序员好得多,所以在新的源代码中出现register是多么可疑。
  • 将注册表或内存位置作为int32访问,然后将其转换为无符号类型根本没有任何意义。如果数据未签名,那么为什么您首先使用签名类型。
  • 使用自制的uint32类型而不是stdint.h的风格很差。

Nit-picks (次要评论)

  • (int32*)演员应该const合格。
  • 循环是不必要的丑陋,可以用for循环替换:

    for(uint32_t i=0; i<2048; i++)
    {
      dest[i] = source[i];
    }
    

答案 1 :(得分:0)

如果PolySpace不知道值ADDR_ARAM_BEGIN,它将假定它可能为NULL(或其类型的任何其他值)。当您明确测试source是否为NULL时,您不会对dest执行相同的操作。

由于sourcedest都是从链接器常量分配的,并且在正常情况下都不应该为NULL,因此不必在控制流中显式测试NULL,而assert()将是首选 - PolySPace识别断言,并将在后续分析中应用约束,但assert()在定义NDEBUG时解析为空(通常在发布版本中),因此不会产生不必要的开销:

const uint32_t* source = (const uint32_t*)&ADDR_SWR4_BEGIN ;
uint32_t* dest = (uint32_t*)&ADDR_ARAM_BEGIN;

// PolySpace constraints asserted
assert( source != NULL ) ;
assert( dest != NULL ) ;

for( int i = 0; i < 2048; i++ )
{
    dest[i] = source[i] ;
}

另一种方法是为PolySpace提供“强制包含”(-include选项)以提供显式定义,以便PolySpace不会将所有可能的值视为在其分析中有效。这也可能会加速分析。

答案 2 :(得分:0)

Polyspace在此处发出红色错误的原因是sourcedest是指向uint32的指针。的确,当你写:

source= (int32*)&ADDR_SWR4_BEGIN

您获取变量ADDR_SWR4_BEGIN的地址并将其分配给source

因此两个指针都指向仅4字节的缓冲区。 然后,不可能像2048个元素的数组一样使用这些指针。 您还应该在source[i]上看到橙色支票,告诉您有关指针source发生了什么的信息。

似乎ADDR_SWR4_BEGINADDR_SWR4_BEGIN实际上包含地址。 在这种情况下,代码应该是:

source = (uint32*)ADDR_SWR4_BEGIN;
dest   = (uint32*)ADDR_ARAM_BEGIN;

如果您在代码中执行此更改,则红色错误消失。