GCC BUG
无意间在编译的时候加上了-static
,于是奇怪的事情出现了,一时间毫无头绪,百思不得其解,下面就举例子描述下。
这个是一个非常简单的程序。
#include <condition_variable>
#include <mutex>
#include <thread>
void foo()
{
std::mutex mtx;
std::unique_lock<std::mutex> lk(mtx);
std::condition_variable cond;
while (true)
{
cond.wait(lk);
}
}
int main()
{
std::thread t(foo);
std::this_thread::sleep_for(std::chrono::seconds(10));
t.join();
}
以上代码动态链接时会一直阻塞,直到被杀死。然而,静态链接时会有两个问题:
- 不加上
sleep_for
,那么程序会在执行到join
时收到SIGSEGV
- 加上
sleep_for
,那么程序会在执行wait
时收到SIGSEGV
当然,这两种情况只在使用g++/clang++链接pthread库时出现。在是用Visual Studio 2017 RC测试时,不管怎样都不会出现上述问题。
那么为什么会出现奇怪的问题呢?仔细查看相关资料后发现wait
这个调用存在两个UB
Calling this function if lock.mutex() is not locked by the current thread is undefined behavior.
Calling this function if lock.mutex() is not the same mutex as the one used by all other threads that are currently waiting on the same condition variable is undefined behavior.
第一个UB是不可能,因为上面代码并没有defer。也就是在构造完成时就已经被锁住了。第二个UB,由于这里只有两个线程,并且mutex没有共享,并不存在多个线程等待同一个条件变量,所以也是不可能的!
就算,以上两个UB都成立,那么为啥动态链接就没事?为啥VS上不管怎么链接都没事?
下面来对比下
下面是FreeBSD11上的结果(clang + libc++)
然后,找到了这个相关的BUG58909,然而这个BUG还没有确认。。