C/ c++未使用的内联函数未定义的引用
C/C++ unused inline function undefined reference
考虑以下代码(这不是特定于pthread的;其他示例,例如那些涉及实时库的示例,也表现出类似的行为):
#define _GNU_SOURCE
#include <pthread.h>
inline void foo() {
static cpu_set_t cpuset;
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}
int main(int argc, char *argv[]) { }
这是一个在C和c++中有效的程序。因此,我将此内容保存到testc.c
和testcpp.cpp
,并尝试构建。
当我在C++
中构建时,我没有错误。当我在C
中构建时,我得到一个未定义的引用错误。现在,这个错误发生在-O1
和-O3
中。是否有办法指示gcc做正确的事情(看到foo
是未使用的,并跳过对pthread_setaffinity_np
定义的要求)?
编辑:我认为这是明显从上下文中,但错误信息是:
/tmp/ccgARGVJ.o: In function `foo':
testc.c:(.text+0x17): undefined reference to `pthread_setaffinity_np'
注意,由于foo
没有在主路径中被引用,g++
正确地完全忽略了该函数,但gcc
没有。
foo
以及随后对pthread_setaffinity_np
的调用都是未使用的。主函数为空。看看吧!不知何故,g++
发现foo
不需要包括在内,随后构建过程没有绊倒,当我们故意省略-lpthread
(并检查与nm
导出的符号确认既不需要foo
也不需要引用pthread_setaffinity_np
)。gcc
的结果输出并没有注意到这个事实。我问这个问题是因为c++和C前端似乎在相同的输入上给出不同的结果。这似乎不是一个ld
问题,因为我希望两条路径给出相同的链接错误,这就是为什么我强调这似乎是一个编译器问题。如果c++和C都有问题,那么是的,我同意这是一个链接问题。
显然你的程序包含一个错误:你声明并调用了函数pthread_setaffinity_np
,但是你从来没有定义它。显然,您忘记提供包含该定义的库。这在C和c++中都是错误的
换句话说,这是不是在C和c++中的有效程序。它违反了c++的"一个定义规则"(以及C中任何类似的规则)。
其余部分取决于编译器是否捕获此错误并为其发出诊断消息。虽然形式上编译器应该捕获它,但实际上链接错误并不总是被编译过程捕获(在该术语的扩展意义上,也包括链接)。
它们是否被抓住可能取决于许多因素。在这种特殊情况下,重要的因素显然是C和c++语言的内联函数属性之间的差异。(是的,它们在C和c++之间确实不同)。我猜,在c++模式下,编译器决定这个内联函数不需要实际的函数体,而在C模式下,它决定生成函数体。
所以,如果这个程序,在某些情况下成功编译,那只是因为你很幸运。你似乎相信一个没有被调用的函数应该被"完全忽略"。C和c++都没有做这样的保证。假设确实缺少pthread_setaffinity_np
的定义,您的程序在C和c++中都是无效的。由于这个原因,拒绝编译它的编译器实际上是具有正确行为的编译器。
考虑到上面的问题,你可能想问问自己,你是否真的关心为什么在C和c++模式下得到不同的错误报告。如果您这样做,则需要对该特定实现的内部机制进行一些研究,并且与语言本身没有太大关系。
在C语言中,inline
关键字不影响函数的联动。因此,foo
具有外部链接,无法优化,因为它可能从另一个翻译单元调用。如果编译器/汇编器将函数放在它们自己的单独的节中,并且链接器能够在链接时丢弃不需要的函数节,它可能能够避免链接错误,但为了正确,由于该程序引用pthread_setaffinity_np
,它必须在某处包含该函数的定义,也就是说,您必须使用-lpthread
或等效的。
inline
函数在默认情况下有简而言之,在某些配置中缺少错误是gcc无法诊断无效程序的原因。这不是你应该期望的行为。
您应该从中吸取的另一个教训是,C和c++远非相同的东西。选择你正在写的,并坚持下去!不要试图在两者之间编写"可互换"的代码,否则您可能会使两者都出现微妙的错误…
inline
只是一个建议,而不是编译器有义务听的东西,所以它不能假设foo
没有在另一个编译单元中使用。
但是,是的,很高兴确切地知道哪一个是未定义的引用,因为你没有发布错误,奇怪的是它出现在C而不是c++编译中。
foo
可能不会在您的源代码中使用,但它几乎肯定会在构建过程的其他地方被引用,因此需要编译。
特别是在链接过程中发生了很多优化,因为链接器可以确定一个函数是"死的",可以被丢弃。
如果在内部,链接器决定将整个程序组装为一次,然后在另一次中进行优化,我希望您看到这个错误(它如何组装整个程序?)
此外,如果要导出函数,则必须对其进行编译、链接并最终输出。
听起来你依赖于编译器/链接器的特定行为
- 2个模板化类的非模板友元函数未定义引用错误
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- 获取线函数未定义错误。无法在字符串中保存可验证的内容
- 链表复制构造函数 |未定义的行为
- 尝试使用 std::函数(未定义的符号)声明模板化类状态时出现链接错误
- 专用纯虚拟模板函数(未定义引用)的另一个问题
- 可视化C++ strtoull 函数未定义
- 绑定C++中的C函数(未定义的引用)
- 函数未定义引用c++
- C++构造函数未定义的引用
- 在同一语句中调用的执行 IO 的函数:未定义或未指定
- 在参数中接受 2 个类的友元函数 - 未定义'Class'
- c++ CreateWindow()函数未定义
- 使用c++中的haskell函数:未定义引用错误
- c++模板变量函数未定义引用
- OpenGL函数未定义glow
- C/ c++未使用的内联函数未定义的引用
- 调用从不兼容类型强制转换的零数据结构的成员函数-未定义
- Cocos2d-x Box2D CContactListener构造函数未定义
- 包括Boost网络库使Windows.h函数未定义