【问题标题】:Can GCC warn about undefined functions in libraries?GCC 可以警告库中未定义的函数吗?
【发布时间】:2021-05-24 07:33:54
【问题描述】:

考虑以下测试项目:

test.h:

#ifndef TEST_H
#define TEST_H

void test1(int);
void test2(int);

#endif /* TEST_H */

text.c:

#include "test.h"

void test1(int x) { (void) x; }

糟糕,我忘了定义test2()!当我这样做时,我想要一些 反馈,最好是拒绝编译,尽管至少有一个警告会很好。但是 GCC 10.2(在 Ubuntu 20.10 上)编译得很好,没有警告:

gcc -Wall -Wextra -Wpedantic -std=c11 -o libtest.o -c test.c

我想我明白为什么了:如果 test2() 实际上是来自另一个库,也许是系统库,该怎么办?让它成为最终将所有内容链接到可执行文件的程序的问题!但我想在那之前知道这件事。在这种情况下,它没有在任何包含的头文件中声明。它没有在任何地方调用。可以检测到吗?

我试过了:

  • --no-undefined 导致 gcc: error: unrecognized command-line option ‘--no-undefined’; did you mean ‘-Wno-undef’?
  • -Wno-undef - 接受但没有警告
  • -z,defs - 接受但没有警告
  • -Wimplicit-function-declaration - 接受但没有警告
  • -Werror=missing-declarations - 我知道这是相反的情况,但我越来越绝望了。

【问题讨论】:

  • 它是链接器(例如ld将此称为未定义(编译器不能)。但是,因为text.c实际上使用test2,编译器将test2的前向声明视为只是 那个。它确实没有text.o 中引用它。声明和不是用法/引用。这完全没问题,也是人们通常想要的……
  • ... 例如,如果有人拨打了#include <math.h>,但从未实际致电(例如)cos,我们不希望抱怨缺少 cos如果我们从不使用它[忘记使用-lm]。在这种情况下,我们可能只需要来自.h#define M_PI ... 而不需要调用任何函数,因此我们不需要需要 -lm。为了得到你想要的,添加一个用法到text.c(例如):int main(void); test1(); test2(); return 0; } 链接器现在将搜索test2并且not找到它,所以它会产生一个错误。跨度>
  • 另一种[更被动]强制检查的方法是获取函数的地址#include "test.h" void test1(int x) { (void) x; } void *check_defined[] = { test1, test2 }; void main(void) { }
  • 您知道您的gcc 命令不会创建静态库吗?它创建了一个具有不寻常名称libtest.a 的静态可执行文件。要创建静态库,您首先使用gcc -c 编译.o 文件,然后使用ar
  • 我收回了,您使用-c 创建了一个具有不寻常名称libtest.a对象文件。在我的系统上file 告诉我它是ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped。一个真正的静态库被描述为current ar archive

标签: c gcc gcc-warning


【解决方案1】:

这是不可能的,因为在组装静态库的阶段没有执行链接。

我建议为您的库提供一个“测试容器”。设置您的构建系统以在您构建库的任何时候构建测试可执行文件。它甚至可能只是与库源在同一目录中的单个 .c 文件,但显然不在作为库一部分的对象列表中。

测试可执行文件调用您希望作为库入口点的所有函数。

为了在发布之前测试库的功能,您无论如何都应该这样做。

【讨论】:

  • 这是我目前使用的方法,这是一个很好的建议。我想知道在尝试构建测试工具之前是否可以停止。但是,如果不是,那就不是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 2015-11-14
相关资源
最近更新 更多