如何检测循环调用?

时间:2011-09-02 10:28:53

标签: c++ deadlock

我一直在寻找导致死锁的原因以及避免和检测它们的策略/工具。

死锁的另一个可能原因是阻塞函数以循环方式调用其他阻塞函数,因此最终调用永远不会返回。

有时这很难发现,特别是在非常大的项目中。

那么,是否有任何工具/库/技术可以自动检测程序中的循环调用?

修改 我主要使用C和C ++进行编码,因此,如果可能,请提供有关适用于这些语言的主题的任何信息。

尽管如此,似乎SO中几乎没有涵盖这个主题,所以其他语言的答案也可以。 虽然如果有人发现它相关的话,那些值得拥有的话题

感谢。

5 个答案:

答案 0 :(得分:1)

尝试获取相同的非重入锁定的循环(或递归)调用是最容易调试的阻塞方案之一:锁定是确定性的,并且可以轻松检查。当应用程序锁定时,启动调试器并查看堆栈跟踪以了解所持有的锁和原因。

关于锁定问题的一般解决方案......您可以查看一些提供互斥排序的库,并检测何时尝试无序锁定互斥锁。这种类型的解决方案可能很难正确实现,但一旦到位它确保您不能进入死锁条件,因为它强制所有进程以相同的顺序获取锁(即,如果进程A持有锁La,并且它尝试获取订单正确的锁Lb,然后它可以成功或锁定,但无论哪个进程持有锁Lb都不能尝试锁定La,因为不会满足排序约束。)

答案 1 :(得分:1)

如果你在Linux上有2个用于检测死锁和竞争条件的Valgrind工具:HelgrindDRD。它们相互补充,值得检查两者的线程错误。

答案 2 :(得分:0)

在Linux中,您可以使用valgrind来检测deadlocks,使用--tool=helgrind

答案 3 :(得分:0)

检测死锁(IMO)的最佳方法是制作一个测试程序,以随机顺序调用所有函数,如30个不同的线程10000次。

如果遇到死锁,可以使用VS2010“Parallel Stacks”窗口。调试 - > Windows->并行堆栈
此窗口将显示所有堆栈,因此您可以找到死锁的方法。

我用来编写线程安全对象的简单策略:
调用公共方法时,线程安全对象应该是安全的,因此在使用它时不会出现死锁。

因此,我们的想法是锁定所有访问对象数据的公共方法 除此之外,你需要确保在类代码中你永远不会使用公共方法。如果你需要使用其中一个公共方法,那么将该方法设为私有,并使用锁定然后调用它的公共方法包装私有方法。

如果你想要更好的锁粒度,你可以为每个拥有自己锁的部分创建对象,并像我建议的那样锁定它。然后使用封装将这些类组合到一个类中。

示例:

class Blah {
  MyData data;
  Lock lock;
public:
  DataItem GetData(int index)
  { 
     ReadLock read(lock);
     return LocalGetData(index);
  }
  DataItem FindData(string key)
  {
     ReadLock read(lock);
     DataItem item;
     //find the item, can use LocalGetData() to get the item without deadlocking
     return item;

  }
  void PutData(DataItem item)
  {
    ReadLock write(lock); 
    //put item in database
  }

private:

  DataItem LocalGetData(int index)
  {
    return data[index];
  }
} 

答案 4 :(得分:0)

您可以找到构建调用图的工具,并检查图表的周期。

否则,有许多策略可以检测死锁或其他循环,但它们都取决于是否有某种支持基础设施。

存在死锁避免策略,与分配锁优先级和根据优先级排序锁有关。但这些需要更改代码并执行标准。