【问题标题】:No deadlock unless linked to pthreads?除非链接到 pthread,否则不会出现死锁?
【发布时间】:2017-05-06 23:35:23
【问题描述】:

为什么除非程序链接到 pthreads,否则创建 std::mutex 死锁实际上不会导致死锁?

下面链接pthreads库时会死锁,如果pthreads没有链接进去就不会死锁。在gcc和clang上测试过。

// clang++ main.cpp -std=c++14 -lpthread
#include <mutex>
int main() {
    std::mutex mtx;
    mtx.lock();
    mtx.lock();
    return 0;
}

我知道如果没有线程库,您实际上不需要互斥锁功能,但是编译器是否知道链接的库?是否可以在此基础上进行优化?

【问题讨论】:

标签: c++ linker pthreads mutex compiler-optimization


【解决方案1】:

下面链接pthreads库时会死锁,如果没有链接pthreads则不会死锁。

这是因为std::mutex::lock 的默认实现什么都不做

编译器是否知道链接的库?

否:编译器只是调用std::mutex::lock 并将mtx 的地址传递给它。行为不同的是该函数的实现

更新:

为了澄清,实现是否能够根据是否已链接库而自行更改?通过宏?

当编译器完成编译时,宏预处理完成,不会产生任何进一步的影响。

也许最好证明一下。假设你有:

int main() { return foo(); }

你能说出上面程序的执行结果是什么吗?不,你不能,因为你不知道foo 做了什么。

现在假设我编译了以下内容:

// foo.c
int foo() { return 0; }

gcc -c foo.c && ar ruv libfoo.a foo.o
gcc main.o -L. -lfoo

现在您可以知道程序将以0 返回码退出。

现在假设我还编译了以下内容:

// bar.c
int foo() { abort(); }

gcc -c bar.c && ar ruv libbar.a bar.o

最后,我把同样的unmodifiedmain.o链接成这样:

gcc main.o -L. -lbar -lfoo

你能说出生成的程序会做什么吗?

你可以:它会随着SIGABRT 而死,并产生一个核心转储。

注意main.o 没有改变,只有main.o 链接的库发生了改变。

这与导致原始程序行为不同的机制完全相同,具体取决于它是否链接到libpthread

【讨论】:

  • 澄清一下,实现是否能够根据是否已链接库而自行更改?通过宏?
  • 为什么允许同一个符号有多个定义?
  • @A-n-t-h-o-n-y 没有链接多个定义。要了解为什么会这样,您可以阅读eli.thegreenplace.net/2013/07/09/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多