Memory while循环Polyspace可能出现运行时错误
我正在使用嵌入式C语言,最近为整个项目运行了MathWorks Polyspace代码验证程序(动态分析),以检查关键的运行时错误。它在While循环中发现了一个bug(红色警告),我正在通过内存寄存器将一些ROM数据复制到RAM中。 代码运行良好,正如预期的那样,但我想问一下,是否有任何解决方案可以安全地删除此警告。请查找下面的代码示例: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
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++;
}
}
警告为红色,具体警告如下:
如果您有任何建议,我们将不胜感激。代码总体上很可疑 错误
。您只需将此指针设置为指向某个地址,因此它显然不会指向NULL。这一行是多余的if(source!=NULL)
- 在访问寄存器/内存时,您没有使用
,因此如果此代码执行多次,编译器可能会做出各种奇怪的假设。这可能是诊断消息的原因volatile
- 使用
关键字是可疑的。这曾经是20世纪80年代的事情,当时编译器很糟糕,无法正确优化代码。如今,他们可以做到这一点,而且比程序员做得好得多,因此在新的源代码中出现register
是可疑的寄存器
- 以
的形式访问寄存器或内存位置,然后将其强制转换为无符号类型是毫无意义的。如果数据没有签名,那么首先为什么要使用签名类型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不知道值
,它将假定它可以为NULL(或其类型的任何其他值)。当您显式测试ADDR\u ARAM\u BEGIN
是否为NULL时,您不会对源代码
执行相同的操作 由于dest
和source
都是从链接器常量分配的,在正常情况下都不应该为NULL,因此无需在控制流中显式测试NULL,最好使用-PolySPace识别断言,并在后续分析中应用约束,但是dest
在定义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提供“强制包含”(
选项)为了提供明确的定义,使得多空间不会考虑所有可能的值在其分析中都是有效的,这也可能会有超速分析的效果。 < P>为什么多空间在这里给出一个红色错误的原因是<代码>源和-include
Dest 是UTIT32的指针。
获取变量source= (int32*)&ADDR_SWR4_BEGIN
的地址,并将其分配给ADDR\u SWR4\u BEGIN
因此,两个指针都只指向4字节的缓冲区。 因此,不可能像2048个元素的数组那样使用这些指针。 您还应该在source
上看到一个橙色的复选框,为您提供有关指针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;