【问题标题】:Why does PC-Lint complain about redeclaration (Error 18)?为什么 PC-Lint 抱怨重新声明(错误 18)?
【发布时间】:2021-07-20 20:46:25
【问题描述】:

请注意,以下代码毫无意义,我只是想重现我在更复杂的代码库中看到的错误。显然,我不会创建具有全局范围的变量来将其传递给仅在该变量所在的一个文件中使用的函数。

我正在运行 PC-Lint 9.00L。

在以下示例中,PC-Lint 抱怨重新声明:

example2.c 18 错误 18: Symbol'testFunction(const struct AnotherExample_t *)' redeclared (Arg. no. 1:qualification) 与第 21 行冲突,文件 example.h,模块 example1.c

代码如下:

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

#include <stdint.h>

typedef struct
{
    volatile uint8_t item1;
    volatile uint8_t item2;
} Example_t;

typedef struct
{
    Example_t * p_items;
    uint8_t something;
    uint16_t somethingElse;
} AnotherExample_t;

extern AnotherExample_t g_externalVariable;

extern void testFunction (AnotherExample_t const * const p_example);  //line 21
    
#endif

example1.c

#include "example.h"
#include <stdio.h>

int main(void)
{
    g_externalVariable.something = 5;
    
    (void)printf("%d", g_externalVariable.something);
    
    testFunction(&g_externalVariable);
    return 0;
}

example2.c

#include "example.h"
#include <stdio.h>

static Example_t p = 
{
    .item1 = 0,
    .item2 = 1,
};

AnotherExample_t g_externalVariable =
{
    .p_items = &p,
    .something = 2,
    .somethingElse = 3,
};

void testFunction (AnotherExample_t const * const p_example)
{  // Line referenced in lint (line 18)
    (void)printf("%d", (int)p_example->somethingElse);
}

为什么 lint 会抛出这个错误?

我尝试过的事情

我注意到,当我删除 const AnotherExample_t 的声明时,投诉就消失了。即 -

extern void testFunction (AnotherExample_t * const p_example);  //example.h

void testFunction (AnotherExample_t * const p_example)  //example2.c
{
    ...
}

我还尝试从 example1.c 进行调用,看看是否有任何改变:

testFunction((AnotherExample_t const * const)&g_externalVariable);

这并没有改变任何东西。

在这两种情况下,我都会收到一条 Info 818 消息:

example2.c 20 Info 818:指针参数“p_example”(第 17 行)可以声明为指向 const

最少的可重现代码

这也会导致同样的错误。

example.h

#ifndef EXAMPLE_H
#define EXAMPLE_H

extern void testFunction (const char * const p_example);
    
#endif

example1.c

#include "example.h"
#include <stdio.h>

int main(void)
{
    char testValue = 'c';
    char * p_testValue = &testValue;
    
    testFunction(p_testValue);
    
    return 0;
}

example2.c

#include "example.h"
#include <stdio.h>

void testFunction (const char * const p_example)
{
    (void)printf("%c", p_example);
}

【问题讨论】:

  • AnotherExample_t const * const p_example -> const AnotherExample_t* p_example。我也打赌这个例子不是minimal reproducible example(如 - 非 minimal
  • @SergeyA 我也试过了,但仍然有同样的错误。
  • 您需要真正处理您的示例并将其最小化。我很确定那里有很多噪音。请发布完整但最少的代码,其中函数签名与我建议的匹配。
  • @SergeyA 添加了一个更好的例子。
  • 嗯,这意味着你的 Lint 有错误。如果您确定这是代码,并且这是 Lint 给您的唯一警告,则意味着 Lint 未能就 printf 格式字符串不兼容的真正问题发出警告,而是报告了绝对正确的函数定义。在这一点上,我唯一能建议的就是向 Lint 维护者提交错误报告。

标签: c static-analysis lint pc-lint


【解决方案1】:

这既不是 PC-Lint 的错误,也不是我的代码中的错误。编译器库中的一些关键字重新定义导致 PC-Lint 在其预处理步骤中去除了一些关键字(例如 constvolatile)。

最终结果是,当我添加 #include &lt;stdio.h&gt; 时,我对 testFunction 的定义将被剥夺其 const 限定符,并且它不再与我的标头中的声明匹配。

我在co-XXXX.lnt 文件中添加了以下选项,错误消失了。

+dconst=const
+dvolatile=volatile

特别感谢 Gimpel 的工作人员,尽管这个版本的 PC-Lint 不再受支持,但他们愿意与我一起解决这个问题。

更新

不幸的是,我没有时间去查找库中 constvolatile 被重新定义的位置,但我找到了比在lint 编译器选项文件。利用 PC-Lint 中的-scavenge 选项,然后运行该选项通过预处理器创建的 .c 文件,会创建一个标头,该标头定义编译器的内置宏以供 PC-Lint 使用。这是我使用的过程。

lint-nt -i"/path/to/my/libraries" -scavenge(*.h) > interim.c

然后,我从 Code Composer Studio 运行了我的代码的标准构建,以验证哪些选项正在使用 cl430 编译器运行。之后,我使用相同的选项通过编译器运行 interim.c - 唯一的例外是我使用 -ppo 选项仅通过预处理器运行它,将生成的文件保存为 interim.lnt。

此时,PC-Lint 手册显示运行:lint -scavenge(clean,interim.lnt)。在我的情况下,似乎只清除了所有数据的文件,所以我跳过了这一步。但是,检查在此步骤之前创建的 interim.lnt 文件显示我的所有宏都是在此文件中创建的。我将它重命名为 lint_header.h 并将以下几行添加到我的 co-MSP430.lnt 文件的开头:

-header(lint_header.h)
+libh(lint_header.h)

我不再对constvolatile 使用+d 选项,现在可以更准确地表示我的库文件在使用PC-Lint 时应该做什么。我也不再有重新声明错误。

【讨论】:

  • 那是……奇怪,供应商 stdio.h 对 #define const 做了什么?
  • 我仍在处理库文件,但这不仅仅是影响 stdio.h。我正在为 TI 的 MSP430 产品线使用代码编写器工作室和 cl430 编译器。我怀疑有一些项目定义的#define 被我尚未追踪的库文件使用,并且在一些 TI 库文件中使用了这些文件(即 - _ti_config.h、linkage.h、sys/ cdefs.h、机器/_types.h 等)。我希望找到一个针对这个编译器的更优雅的解决方案。不幸的是,我还没有看到一个适用于 cl430 的好的 lint 编译器选项文件。
猜你喜欢
  • 2018-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
相关资源
最近更新 更多