首页 > 解决方案 > 如何将 .h 文件中的外部符号验证为 .c 文件?

问题描述

C让您的文件包含相应文件中外部可见符号的声明是一种惯用.h模式.c。这样做的目的是为了支持一种“模块和接口”思维,例如启用更简洁的结构。

在我正在研究的大型遗留 C 系统中,可能在将函数移动到另一个模块之后,在错误的头文件中声明函数并不少见,因为它仍然可以编译、链接和运行,但这使得模块在它们的接口并指示错误的依赖关系。

有没有办法验证/确认/保证.h文件包含所有外部符号,.c并且没有外部符号不存在?

例如,如果我有以下文件

模块.c

int func1(void) {}
bool func2(int c) {}
static int func3(void) {}

模块.h

extern int func1(void);
extern bool func4(char *v);

我想指出这样一个事实,即func4它不是外部可见符号module.c并且func2缺失了。

现代编译器提供了一些帮助,它们可以检测到您实际引用的缺失声明,但它并不关心它来自哪个文件。

除了手动检查每一对之外,我还有哪些选择来获取此信息?

标签: cheader-files

解决方案


我想指出 func4 不是 module.c 中的外部可见符号并且缺少 func2 的事实。

使用 POSIX-ish linux 和bash,diffctags给出输入文件的非常简单的例子,你可以这样做:

$ #recreate input
$ cat <<EOF >module.c
int func1(void) {}
bool func2(int c) {}
static int func3(void) {}
EOF
$ cat <<EOF >module.h
extern int func1(void);
extern bool func4(char *v);
EOF
$ # helper function for extracting only non-static function declarations
$ f() { ctags -x --c-kinds=fp "$@" | grep -v static | cut -d' ' -f1; }
$ # simply a diff
$ diff <(f module.c) <(f module.h)
2,3c2
< func2
---
> func4
$ diff <(f module.c) <(f module.h) |
> grep '^<\|^>' |
> sed -E 's/> (.*)/I would like to point the fact that \1 is not externally visible symbol/; s/< (.*)/\1 is missing/'
func2 is missing
I would like to point the fact that func4 is not externally visible symbol

如果例如static关键字与引入的函数标识符不在同一行,这将中断,因为ctags不会输出它们。所以真正的工作是获取外部可见的函数声明列表。这不是一件容易的事,编写这样的工具留给其他人:)


推荐阅读