Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;编译并链接指向未定义函数的指针_C++_Linker_Static Assert - Fatal编程技术网

C++ C++;编译并链接指向未定义函数的指针

C++ C++;编译并链接指向未定义函数的指针,c++,linker,static-assert,C++,Linker,Static Assert,此代码: void undefined_fcn(); void defined_fcn() {} struct api_t { void (*first)(); void (*second)(); }; api_t api = {undefined_fcn, defined_fcn}; 使用指向不存在函数的指针定义全局变量api。然而,令我惊讶的是,它编译的链接完全没有来自GCC的抱怨,即使有那些-Wall-Wextra-Werror-pedantic标志 此代码是共享库的一

此代码:

void undefined_fcn();
void defined_fcn() {}

struct api_t {
    void (*first)();
    void (*second)();
};
api_t api = {undefined_fcn, defined_fcn};
使用指向不存在函数的指针定义全局变量
api
。然而,令我惊讶的是,它编译的链接完全没有来自GCC的抱怨,即使有那些
-Wall-Wextra-Werror-pedantic
标志

此代码是共享库的一部分。只有当我在运行时加载库时,它才最终失败。在库链接时,如何检查我是否忘记定义任何函数



更新:提到同样的问题,答案是一样的:
-Wl,--no-undefined
。(顺便说一下,我想这甚至可以标记为重复)。但是,根据下面公认的答案,在使用
-Wl,--no undefined

时应该小心。您不能让编译器告诉您是否忘记在该实现文件中定义函数。原因是当您定义函数时,它在C++中隐式地标记为“代码> ExtNe<代码”。并且,在链接共享库之前,您无法分辨该库中的内容(编译器的链接器不知道引用是否已定义)

如果您不熟悉
extern
的含义。标记为
extern
的东西表示外部链接,因此如果您有一个变量是
extern
,编译器不需要在使用该变量的转换单元中定义该变量。定义可以在另一个实现文件中,并且在链接时解析引用(当您链接定义变量的转换单元时)。这同样适用于函数,函数本质上是函数类型的变量

要获得所需的行为,请使函数
静态
,该函数告诉编译器该函数不是
外部
,并且是当前翻译单元的一部分,在这种情况下,必须对其进行定义
-Wundefined internal
-Wundefined internal
-Werror
的一部分,因此只需使用它编译即可)

此代码是共享库的一部分

这是关键。拥有一个共享库的全部目的就是拥有一个“不完整的”具有未定义符号的共享对象,当主可执行文件加载该对象及其链接的所有其他共享库时,必须解析这些符号。此时,运行时加载程序尝试解析所有未定义符号;并且必须解析所有未定义符号,否则可执行文件将无法启动

您声明您使用的是
gcc
,因此您可能使用GNU
ld
。出于上述原因,
ld
将使用未定义的符号链接共享库,但将无法链接可执行文件,除非根据可执行文件链接的共享库解析所有未定义的符号。因此,在运行时ected行为是,运行时加载程序预期也会成功解析所有符号;因此,运行时加载程序无法启动可执行文件的唯一情况将指示致命的运行时环境故障(例如,共享库被不兼容的版本替换)

有一些选项可用于覆盖此行为。
--no undefined
选项指示
ld
在链接共享库时报告未定义符号的链接失败,就像可执行文件一样。当通过
gcc
间接调用
ld
时,这将成为
-Wl,-no undefined

<>但是,你可能会发现这将是一个失败的命题。你最好希望你的共享库中的代码中没有一个在标准C++或C库中使用<强>任何< /强>类。因为,猜猜什么?-那些引用将是未定义的符号,并且你将无法链接共享库!


换句话说,这是你需要处理的一个必要的问题。

谢谢。我知道我在编译时无法获得帮助,因为该函数可能在另一个翻译单元中定义。但是为什么我在链接时无法获得帮助呢?为什么链接器没有意识到我试图获取指向不存在对象的指针呢?@fonini我猜是这样的链接器在链接后才知道共享对象包含什么(因为它是动态链接的)实际上,我试过了,如果我把问题中的代码直接放在可执行文件中,GCC仍然不会抱怨:\n如果我不尝试实际调用未定义的函数,一切都会发生smoothly@fonini这很奇怪,我的代码在指向一个未定义的函数时出现了一个错误。你说得对,我定义了两个函数。哎呀。(但这在可执行文件中;在共享库中,它仍然接受未定义的函数)正如另一个答案中的评论所述,问题不在于它是一个动态链接的共享库。我尝试了它,并且我在问题中所说的一切在直接编译/链接最终可执行文件时都是有效的。除了共享库上没有链接失败的原因正是我在回答中解释的,如果您想知道如何触发共享库中未定义引用的链接失败,说明在我的回答中,但是,正如我所解释的,您会发现您实际上并不想这样做。实际上,我尝试过,我可以在
-Wl,--no undefined
下调用
malloc
free
。也许是因为glibc是静态链接的?顺便说一句,我认为,
-Wl,--没有未定义的
对我有效,谢谢!我想知道你是否理解他的答案,或者我自己是否误解了。动态链接的整个要点是,在你执行所以链接器必须在链接时让它通过,除非它是静态链接的。