【问题标题】:Deadlock in __cxa_guard_acquire__cxa_guard_acquire 中的死锁
【发布时间】:2018-08-21 20:59:41
【问题描述】:

首先是代码:

#pragma once
#include <type_traits>

// assign unique identifiers to types
template<typename ...>
class Family
{
static std::size_t identifier() noexcept
{
  static std::size_t value = 0;
  return value++;
}

template<typename ...>
static std::size_t family() noexcept
{
  static const std::size_t value = identifier();
  return value;
}
public:
using family_type = std::size_t;
template<typename ... Type>
static family_type type() noexcept
{
  return family<std::decay_t<Type>...>();
}
};

// usage
using introspection_family = Family<struct IntrospectionRegistry>;

template<typename Structure>
void addIntrospectData(DataType introspection[MAX_TYPES], DataType const& dataType)
{
  /* reserve index for this type in the introspection register */
  const auto num = introspection_family::type<Structure>();
  assert(num < MAX_TYPES);
  introspection[num - 1] = dataType;
}

这段代码为每种类型提供一个整数,我在某种 C++ 内省实现中使用它。

应用程序不是多线程的。 当我在-O0 中编译它时,有时,对introspection_family::type&lt;Structure&gt;() 的调用会在__cxa_guard_acquire@plt 处阻塞,我会遇到死锁。

当使用-O3编译时,我没有任何问题,但这可能只是因为它变得非常难以重现。

__cxa_guard_acquire 用于确保在我们访问它之前构造静态变量,但在这里它应该无关紧要,因为我什至不在线程应用程序中。

有人知道为什么会这样吗?

我用:

CXXFLAGS=-std=c++14 -O0 -g3 -pthread -Wall -Wextra -Werror
LDFLAGS= -g -pthread -lGLEW -lGLU -lGL -lSDL2_mixer -lSDL2 

我使用gcc(Ubuntu 5.4.0-6ubuntu1~16.04.10)5.4.0 20160609

【问题讨论】:

  • 我的问题恰恰是我没有。当我在一个单独的主目录中提取它时,我没有遇到任何死锁。
  • 添加 -pthread 不会改变行为。这是我使用的编译标志: CXXFLAGS=-std=c++14 -O0 -g3 -pthread -Wall -Wextra -Werror LDFLAGS= -g -pthread -lGLEW -lGLU -lGL -lSDL2_mixer -lSDL2 我使用 gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
  • @SergeiKurenkov 进程中只有一个线程(但我仍会尽我所能检查互斥锁,因为它确实应该由这个线程持有。)
  • identifier() 里面的std::size_t family() 是什么?

标签: c++ templates static


【解决方案1】:

添加编译选项-fno-threadsafe-statics 有帮助。由于您的应用程序是单线程的,这没关系。

我遇到了类似的问题。但是,我的代码中的原因是 recursion__cxa_guard_acquire 会在递归调用时阻塞。需要进行适当的修复。如果这也可能是您的问题,我没有检查您的代码。

附加信息:使用的锁的名称可能与 __cxa_guard_acquire 不同。它也可能适用于递归,但这是特定于编译器/libc++ 的,您不应依赖它。

【讨论】:

  • 这可能是问题所在,因为在示例中我有一个静态正在初始化另一个静态。但它并没有一直发生,所以这很奇怪......用另一个静态初始化一个静态应该可以工作。
  • 哦,你的意思是无限递归,例如 manishearth.github.io/blog/2015/06/26/…
  • 我快速浏览了这篇文章。是的,就像文章最后一个例子中的递归。
猜你喜欢
  • 2014-08-26
  • 2020-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多