函数形参生命周期及相关C++代码死锁问题的技术问询
函数形参生命周期及相关C++代码死锁问题的技术问询
各位好,我最近在调试一段C++代码时碰到了疑似死锁的问题,还牵扯到函数形参生命周期的疑问,想跟大家探讨下。
我测试了不同的编译器和C标准版本,发现这段代码至少在gcc8、C11环境下能复现死锁情况,相关注释还指出这属于未定义行为(UB)。为了搞清楚根源,我查看了这段代码的汇编实现,发现一个关键细节:foo1函数的形参q,直到main里的整个调用语句执行完毕才会被销毁。
下面是这段有问题的代码:
#include <iostream> #include <memory> #include <mutex> std::mutex mtx; int foo1(std::unique_lock<std::mutex> q) { std::cout << "foo1" << std::endl; return 0; } void foo2(int _v) { std::unique_lock<std::mutex> q(mtx); std::cout << "foo2" << std::endl; } int main() { foo2(foo1(std::unique_lock<std::mutex>(mtx))); return 0; }
简单梳理下执行流程:在main中调用foo2时,会先计算它的实参——也就是调用foo1,而foo1的实参是一个临时的std::unique_lock<std::mutex>,它会先锁住mtx。根据我观察到的汇编结果,foo1的形参q(也就是那个临时锁的移动/拷贝对象)并不会在foo1返回后立刻销毁,而是要等到foo2(foo1(...))这条语句完全执行完才会释放锁。这就导致foo2内部尝试再次锁住mtx时,锁已经被持有,进而造成死锁。
想请教下各位大佬,这个形参生命周期的问题是不是导致死锁的根本原因?另外,C++标准对于这种场景下的形参生命周期具体是怎么规定的呢?
内容来源于stack exchange
相关产品推荐
相关产品推荐

