Memory while循环Polyspace可能出现运行时错误

Memory while循环Polyspace可能出现运行时错误,memory,embedded,runtime-error,dynamic-analysis,Memory,Embedded,Runtime Error,Dynamic Analysis,我正在使用嵌入式C语言,最近为整个项目运行了MathWorks Polyspace代码验证程序(动态分析),以检查关键的运行时错误。它在While循环中发现了一个bug(红色警告),我正在通过内存寄存器将一些ROM数据复制到RAM中。 代码运行良好,正如预期的那样,但我想问一下,是否有任何解决方案可以安全地删除此警告。请查找下面的代码示例: register int32 const *source; uint32 i=0; uint32 *dest; source= (int32*)&A

我正在使用嵌入式C语言,最近为整个项目运行了MathWorks Polyspace代码验证程序(动态分析),以检查关键的运行时错误。它在While循环中发现了一个bug(红色警告),我正在通过内存寄存器将一些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++;
        }
     }
警告为红色,具体警告如下:


如果您有任何建议,我们将不胜感激。

代码总体上很可疑

错误

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

  • 使用
    register
    关键字是可疑的。这曾经是20世纪80年代的事情,当时编译器很糟糕,无法正确优化代码。如今,他们可以做到这一点,而且比程序员做得好得多,因此在新的源代码中出现
    寄存器
    是可疑的
  • int32
    的形式访问寄存器或内存位置,然后将其强制转换为无符号类型是毫无意义的。如果数据没有签名,那么首先为什么要使用签名类型
  • 使用自制的
    uint32
    类型而不是
    stdint.h
    是糟糕的风格
吹毛求疵(小评论)

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

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

    for(uint32\u t i=0;i如果PolySpace不知道值
    ADDR\u ARAM\u BEGIN
    ,它将假定它可以为NULL(或其类型的任何其他值)。当您显式测试
    源代码
    是否为NULL时,您不会对
    dest
    执行相同的操作

    由于
    source
    dest
    都是从链接器常量分配的,在正常情况下都不应该为NULL,因此无需在控制流中显式测试NULL,最好使用-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] ;
    }
    
    const uint32\u t*源=(const uint32\u t*)和ADDR\u SWR4\u BEGIN;
    uint32目的地=(uint32目的地)和地址开始;
    //多空间约束断言
    断言(源!=NULL);
    断言(dest!=NULL);
    对于(int i=0;i<2048;i++)
    {
    dest[i]=源[i];
    }
    

    另一种方法是为PolySpace提供“强制包含”(
    -include
    选项)为了提供明确的定义,使得多空间不会考虑所有可能的值在其分析中都是有效的,这也可能会有超速分析的效果。

    < P>为什么多空间在这里给出一个红色错误的原因是<代码>源和Dest是UTIT32的指针。
    source= (int32*)&ADDR_SWR4_BEGIN
    
    获取变量
    ADDR\u SWR4\u BEGIN
    的地址,并将其分配给
    source

    因此,两个指针都只指向4字节的缓冲区。 因此,不可能像2048个元素的数组那样使用这些指针。 您还应该在
    source[i]
    上看到一个橙色的复选框,为您提供有关指针
    source
    的信息

    似乎
    ADDR\u SWR4\u BEGIN
    ADDR\u SWR4\u BEGIN
    实际上包含地址。 在这种情况下,代码应为:

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

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

    “它在While循环中发现一个错误”消息是什么?您如何知道这是一个错误?“无限循环或运行时错误”。没有编译器或链接器错误。为了准确回答您的问题,您可以添加ADDR_SWR4_BEGIN和ADDR_ARAM_BEGIN的定义吗?顺便问一下,您是否看到红色复选框或橙色复选框(您使用的是术语“警告”)?@codetest:你需要在你的问题中提供准确的逐字诊断,而不是在评论中解释。编辑问题,复制并粘贴诊断。@AlexDeba我编辑了我的帖子。我希望它能让问题更清楚。嘿,非常感谢你的详细分析。我一定会采纳你的建议。这是对cod的批评e、 这不是问题的答案。你可能不知道什么是PolySpace吗?@Clifford还有另一个几乎破碎的静态分析器,充满了误报。一个工作工具不应该假设声明不可见,它应该要求项目范围内的设置。尽管OP给人的印象是诊断来自动态分析,这更有意义。@Lundin:PolySpace不是一个传统的静态分析器。它使用抽象执行来捕获在动态分析中可能会发现的错误类型,除非碰巧执行了错误路径而没有“幸运”。它不仅是(事实上很少)用于整个系统,但可用于测试部分系统。在这种情况下,表示“对于未知变量或参数的某些值,此代码将失败”这是正确的-代码本身是不安全的,但在上下文中它可能永远不会失败。工具没有损坏,而是结果不被理解。@Lundin:这里的问题是对工具缺乏理解,而不是工具错了。工具只是给出了与用户不同的问题的答案,或者你认为是被问到的问题。例如,它不会执行与-Wconversion.To thin相同的检查
    source= (int32*)&ADDR_SWR4_BEGIN
    
    source = (uint32*)ADDR_SWR4_BEGIN;
    dest   = (uint32*)ADDR_ARAM_BEGIN;