c++ - C/C++ 代码中函数的多重定义

标签 c++ c r

这是一道关于C/C++函数定义的题。讨论的代码是 staticlibRmath,它在 RRmath.h 头文件中提供定义。

为库提供的 documentation 表明用户可以选择为函数 double unif_rand(void) 提供函数定义。

所以我的问题是,如果这样的函数定义是可选的,会不会出现C/C++中不允许的多个函数定义的问题?

编辑: 在不查看源代码的情况下推测事情是如何工作的可能很诱人,但这不是我想要的。我很想知道它真正 是如何工作的,因此您可能需要阅读 source codedocumentations 才能回答这个问题。

最佳答案

当您的应用程序被链接时,未解析的符号将使用您提供的库进行解析。如果您不定义函数,它将在链接期间成为未解析的符号,因此,在这种情况下,链接将尝试使用 librmath 解析该符号。如果无法解析一个或多个符号,您将收到链接器错误。

但是,如果您确实在代码中定义了该函数,那么它将在链接期间已经定义,因此无需使用来自外部库的符号来解析它。

您不能做的是在您的应用程序中多次定义相同的符号。

编辑:由于在另一个答案中有很多争论,我做了一个实际的例子。我创建了一个共享对象(类似于 Windows 中的 DLL),它定义并导出了一个函数 foo:

//lib.h
extern "C" {
    void foo();
    void bar();
};

//lib.cpp
#include <iostream>
#include "lib.h"

void foo() {
    std::cout << "From lib\n";
}

void bar() {
    std::cout << "Bar, calling foo\n";
    foo();
}

为了测试这个共享对象,我创建了一个与之链接的应用程序:

//test.cpp
#include <iostream>
#include "lib.h"

void foo() {
    std::cout << "From app\n";
}

int main() {
    bar();
}

我已经编译了共享对象和应用程序:

g++ lib.cpp -o libtest.so -Wall -fPIC -shared -Wl,--export-dynamic -Wl,-soname,libtest.so -Wl,-z,defs
g++ test.cpp -o test -L. -ltest

当我执行 test 时,将库路径设置为 ".",这样我的共享对象就可以加载了,我得到了这个输出:

matias@master:/tmp$ LD_LIBRARY_PATH="." ./test
Bar, calling foo
From app

如您所见,调用了应用程序(而非共享对象)中定义的foo 函数。您基本上可以为共享对象中的每个导出符号执行此操作。

EDIT2:我在 lib.h 中添加了另一个导出函数。应用程序现在调用此函数,最终调用 foo。结果与预期相同。

EDIT3:好的,让我们更深入一点。这是函数 bar 的转储:

Dump of assembler code for function bar@plt:
   0x0804855c <+0>: jmp    DWORD PTR ds:0x804a004
   0x08048562 <+6>: push   0x8
   0x08048567 <+11>:    jmp    0x804853c

如果我们转到地址 0x804a004:

Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
   0x08049ff4 <+0>: or     BYTE PTR [edi+0x804],bl
   0x08049ffa <+6>: add    BYTE PTR [eax],al
   0x08049ffc <+8>: add    BYTE PTR [eax],al
   0x08049ffe <+10>:    add    BYTE PTR [eax],al
   .....

如您所见,它正在跳转到全局偏移表。您可以阅读 GOT herehere .动态符号(在运行时解析)存储在该表中。每当你调用一个应该在运行时解析的符号时,你实际上是跳转到这张表,然后跳转到存储在这张表对应表项中的地址。由于应用程序定义了 foo,因此 GOT 包含来自 test.cpp 的定义地址,而不是我们共享对象中的地址。

EDIT4:好的,最后编辑。引用文档:

You will need to supply the uniform random number generator

 double unif_rand(void)

or use the one supplied (and with a dynamic library or DLL you will have to use the one supplied(...)

文档明确指出,如果您使用的是动态库,则不能提供您自己的 unif_rand 实现。因此,我相信我所指出的实际上回答了您的问题。

关于c++ - C/C++ 代码中函数的多重定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9882089/

相关文章:

r - 如何在数据框中插入新行以使其行号等于R中给定向量的长度

c++ - 从 std::string 中提取(第一个)UTF-8 字符

c++ - 用 vector 模拟行星轨道

C: printf 没有立即输出

r - 如何删除geom_errorbar中误差线的末端

R/考试 : implement only six boxes for the registration number

c++ - 通用删除功能

c++ - 从 CPropertyPageImpl 打开 CDialogImpl

c - 哪个更快,乘法还是减法?

c - 在 C 中查找最小值和最大值的问题