这个问题与在没有线程支持的程序加载的共享库中使用 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++ 版本相同,我可以检查什么来找出为什么它会在一种环境中发生而不在另一种环境中发生?