Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.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++_Dynamic Linking_Undefined Symbol - Fatal编程技术网

C++ .那么,没有正确依赖项的文件为什么可以工作

C++ .那么,没有正确依赖项的文件为什么可以工作,c++,dynamic-linking,undefined-symbol,C++,Dynamic Linking,Undefined Symbol,我无意中遇到了这个问题 // foo.cpp #include <iostream> int i; extern "C" { void pn() { std::cout << "Hello!" << std::endl; } } 然后是bar.cpp // bar.cpp #include <dlfcn.h> #include <stdio.h> #include <iostream>

我无意中遇到了这个问题

// foo.cpp
#include <iostream>

int i;

extern "C" {
    void pn() {
        std::cout << "Hello!" << std::endl;
    }
}
然后是
bar.cpp

// bar.cpp
#include <dlfcn.h>
#include <stdio.h>
#include <iostream>

using namespace std;

extern "C" {
    int decode();
}

int decode() {
    void *handle = dlopen("libfoo.so", RTLD_LAZY);
    if (!handle) {
        printf("%s \n", dlerror());
        return 1;
    }
    void (*pn)() = (void (*)()) dlsym(handle, "pn");
    (*pn)();
    return 0;
}
// main.cpp
#include <dlfcn.h>
#include <stdio.h>

// Magic sauce
//#include <iostream>
//using namespace std;

int main() {
    void *handle = dlopen("libbar.so", RTLD_LAZY);
    if (!handle) {
        printf("%s \n", dlerror());
        return 1;
    }
    int (*pn)() = (int (*)()) dlsym(handle, "decode");
    (*pn)();
    return 0;
}
decode
main.cpp
中调用

// bar.cpp
#include <dlfcn.h>
#include <stdio.h>
#include <iostream>

using namespace std;

extern "C" {
    int decode();
}

int decode() {
    void *handle = dlopen("libfoo.so", RTLD_LAZY);
    if (!handle) {
        printf("%s \n", dlerror());
        return 1;
    }
    void (*pn)() = (void (*)()) dlsym(handle, "pn");
    (*pn)();
    return 0;
}
// main.cpp
#include <dlfcn.h>
#include <stdio.h>

// Magic sauce
//#include <iostream>
//using namespace std;

int main() {
    void *handle = dlopen("libbar.so", RTLD_LAZY);
    if (!handle) {
        printf("%s \n", dlerror());
        return 1;
    }
    int (*pn)() = (int (*)()) dlsym(handle, "decode");
    (*pn)();
    return 0;
}
我使用ldd检查
libfoo
的依赖项

linux-vdso.so.1 =>  (0x00007ffd5b75e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2d9677a000)
/lib64/ld-linux-x86-64.so.2 (0x0000563d0c838000)
如果我在
main.cpp
中使用
iostream
,这会导致main依赖于
libstdc++.so
。然后这个
main
运行没有任何问题。但是如果<代码>主< /代码>不包含C++用法,可执行文件断裂。

./libfoo.so: undefined symbol: _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
我已经挣扎了三天了。谢谢你的帮助


我知道使用
g++
编译
foo.cpp
是正确的选择。我只是想了解这里发生了什么。

如果不使用
iostream
,它就会失败,因为编译器看到的主文件不依赖于
libstdc++
,而是依赖于
foo.cpp
/
foo。所以
依赖于
libstdc++

你可能想知道为什么仅仅一个
#include
就能解决这个问题。这是因为,
iostream
实际上只是通过被包含而完成了一些工作。例如,它设置
std::cout
。因此,虽然您可能认为程序代码没有更改,但实际上已经更改了-
\include
添加了静态初始化,这取决于
libstdc++


这类问题(编译器看不到的间接依赖项)的一般解决方案如下:

当您不使用
iostream
时,它会失败,因为编译器看到的主文件不依赖于
libstdc++
,而是
foo.cpp
/
foo。因此
依赖于
libstdc++

你可能想知道为什么仅仅一个
#include
就能解决这个问题。这是因为,
iostream
实际上只是通过被包含而完成了一些工作。例如,它设置
std::cout
。因此,虽然您可能认为程序代码没有更改,但实际上已经更改了-
\include
添加了静态初始化,这取决于
libstdc++


这类问题(编译器看不到的间接依赖)的一般解决方案如下:

您应该使用g++而不是gcc来编译libfoo.so。然后
libstdc++
将被添加到libfoo.so的依赖项中。

您应该使用g++而不是gcc来编译libfoo.so。然后,代码<> LBSTDC++< /COD>将添加到LIbFO中。所以依赖性。

< P>你应该真正坚持一种语言,不要像你那样混合C和C++(只要你不知道你在做什么(没有冒犯、经验))!为什么您的代码中只有
C++
部分是使用
C
编译器编译的

使用g++而不是gcc编译libfoo:

g++ -fPIC --shared foo.cpp -o libfoo.so
更新 我只是想了解这里发生了什么事

我认为正在发生的事情是多种多样的

  • 首先,gcc和g++不仅仅是编译器程序,还包括编译器、链接器等。它们都会自动决定使用
    C
    编译器或
    C++
    编译器/链接器(选项)。所以你的foo.cpp编译得非常完美
  • 第二个
    std::cout
    定义为
    extern
    (来自我的cygwin安装的代码
    extern ostream cout;///链接到标准输出
    )。这意味着,在链接libfoo.so时,链接器不必链接到libstdc++.so.X,因为它可以是来自另一个链接器单元的依赖项(请参见3.)PLUS使用gcc链接器甚至不会尝试
  • 当您向主应用程序添加iostream时,gcc会识别这一点,并使用其他链接器选项生成二进制文件。您可以使用
    -v
    选项查看gccg++之间的差异,您应该看到库路径将有所不同。在COLLECT_GCC_OPTIONS中也使用g++时,会出现-lstdc++选项。如果使用g++编译libfoo,那么这就是依赖性
    libstdc++.so.6=>/usr/lib/x86\u 64-linux-gnu/libstdc++.so.6
    的原因
  • 当您使用dl作为加载选项时,您的共享对象本身或(依赖于操作系统)您的可执行文件应该包含正确的库,而不考虑一些中间人(在您的例子中是libbar)。如果没有,您将看到错误注意:我不建议您依赖可执行文件,因为它依赖于操作系统,可能无法在其他*nix上工作
  • 这是一个你可以玩的例子。尝试将
    gcc-D MAINDEF-Wall--pedantic--pedantic errors-ldl-lstdc++main.cpp-o main
    更改为g++或删除
    -lstdc++
  • 简而言之:正如前面所说的,使用正确的编译器才是正确的选择!错误不在libbarmain内,因为此单元不应对libfoo的正确库依赖项负责

    […]我无法访问他们的源代码。[…]


    告诉那家伙去解决他们的关系C++
    部分是使用
    C
    编译器编译的

    使用g++而不是gcc编译libfoo:

    g++ -fPIC --shared foo.cpp -o libfoo.so
    
    更新 我只是想了解这里发生了什么事

    我认为正在发生的事情是多种多样的

  • 首先,gcc和g++不仅仅是编译器程序,还包括编译器、链接器等。它们都会自动决定使用
    C
    编译器或
    C++
    编译器/链接器(选项)。所以你的foo.cpp编译得非常完美
  • 第二个
    std::cout
    定义为
    extern
    (代码来自我的cygwin安装
    extern ostream cout;///链接到标准