0

这个问题与在没有线程支持的程序加载的共享库中使用 C++11 多线程非常相似

我有一个使用 OpenMP 的共享库和一个主程序,它从中调用一个函数。

测试库.cpp

#include <memory>
void foo(std::shared_ptr<int> f)
{
#pragma omp parallel for
    for (size_t g = 0; g < 100; g++) {
        auto other = f;
    }
}

测试器.cpp

#include <memory>
void foo(std::shared_ptr<int> f);
int main() {
        foo(std::make_shared<int>(4));
}

我编译并链接:

g++ -fPIC -g -shared -o libtestlibd.so testlib.cpp -openmp -pthread
g++ -g tester.cpp -o tester -Wl,-rpath,`pwd` libtestlibd.so

但是,当在具有自定义(自动)构建编译器的机器上运行它时,这会与“调用纯虚拟方法”、“SIGSEV”和类似的崩溃,即使它不应该__gthread_active_p返回,毕竟程序是(传递性的)false链接到libpthread

使用gdb,我在函数内部设置断点,__gthread_active_p当包含的指针是否为NULL 时触发条件,即函数将返回true 或false。然后我比较了回溯和变量的地址:

  • 在这两种情况下,对的调用都__gthread_active_p来自foo,因此来自共享库
  • 变化的地址,__gthread_active_ptr设置或不设置
  • 但是情况__gthread_active_p是,根据函数的地址,当调用主程序中的shared_ptr析构函数时,我猜动态链接器找到了它的2个定义并选择使用主程序中的一个

在我的 Linux Mint 20 系统上执行相同操作时,程序运行并调试它表明使用了来自共享库的析构函数。

如果我用 显式链接主程序,它也可以工作,-lpthread尽管我已经将它与链接 pthread 的共享库链接。

函数和引用的__gthread_active_p变量都是静态的,即翻译单元的本地变量。因此,只有我的 2 个 cpp 文件很重要。

所以我的问题是:

  • 为什么在初始化主程序的静态变量之前没有加载libpthread?
  • 该函数甚至包含一个static void *const我的理解应该只在第一次调用该函数时初始化。这似乎不是真的,调试器显示来自共享库内部的第一个调用,所以在加载 pthread 之后。为什么?
  • 这是 libstdc++ 中的错误吗?这听起来像是你需要知道的一个巨大的脚枪,如果你的任何共享库使用线程,如果是的话也链接到 pthread。
  • 鉴于 GCC 和 libstdc++ 版本相同,我可以检查什么来找出为什么它会在一种环境中发生而不在另一种环境中发生?
4

0 回答 0