我正在使用嵌入式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
任何建议都将不胜感激。
答案 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
执行相同的操作。
由于source
和dest
都是从链接器常量分配的,并且在正常情况下都不应该为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在此处发出红色错误的原因是source
和dest
是指向uint32的指针。的确,当你写:
source= (int32*)&ADDR_SWR4_BEGIN
您获取变量ADDR_SWR4_BEGIN
的地址并将其分配给source
。
因此两个指针都指向仅4字节的缓冲区。
然后,不可能像2048个元素的数组一样使用这些指针。
您还应该在source[i]
上看到橙色支票,告诉您有关指针source
发生了什么的信息。
似乎ADDR_SWR4_BEGIN
和ADDR_SWR4_BEGIN
实际上包含地址。
在这种情况下,代码应该是:
source = (uint32*)ADDR_SWR4_BEGIN;
dest = (uint32*)ADDR_ARAM_BEGIN;
如果您在代码中执行此更改,则红色错误消失。