boost named_mutex 私有成员访问错误

boost named_mutex private member access error

我遇到了一个问题,我需要 named_mutex 用于 class 中的 managed_shared_memory 成员,但出现 "cannot access private member declared in class boost::interprocess::named_mutex" 错误。但是,我都从 boost::noncpoyable 派生了我的 class 并在构造函数中使用了带有移动语义的 std::unique_ptr,但没有成功。使用boost 1_60和VS 2010,代码如下:

class FileLocker : private boost::noncopyable
{
public:
    FileLocker();
    ~FileLocker();

private:
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

cpp 文件:

FileLocker::FileLocker()
{
  m_oShMem = managed_shared_memory(open_or_create, m_oMemName.c_str(), 1024);
  m_oSetFileMutex = make_unique<named_mutex>( m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")() );
}

最后是唯一的:

template<typename T>
std::unique_ptr<T> make_unique()
{
    return std::unique_ptr<T>( new T() );
}

template<typename T, typename Ts>
std::unique_ptr<T> make_unique(Ts&& params)
{
    return std::unique_ptr<T>( new T(std::forward<Ts>(params)) );
}

我阅读了几个关于这个问题的 Whosebug-Threads,但它们都指出了我处理过的不可复制性...

感谢帮助!

首先,boost::noncopyable不可移动。因此,除非您编写自定义移动 constructor/assignment(五法则),否则您将永远无法获得活字。如果基础不可移动,编译器无法生成默认的移动特殊成员。

这是天真的修正 class:

Live On Coliru

#include <memory>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

class FileLocker
{
public:
    FileLocker() { }
    ~FileLocker() { }

    // non-copyable:
    FileLocker(FileLocker const&)             = delete; // noncopyable
    FileLocker& operator==(FileLocker const&) = delete; // noncopyable

    // movable
    FileLocker(FileLocker&&) = default;

private:
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

int main() {
    FileLocker fl;
    auto moved = std::move(fl);
}

但鉴于 managed_shared_memory 已经 不可复制,您可以利用 Rule Of Zero:

Live On Coliru

#include <memory>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

class FileLocker {
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

int main() {
    FileLocker fl;
    auto moved = std::move(fl);

    //auto copy = moved; // doesn't compile
}

撇开其他问题不谈,您在两个地方错误地调用了 named_mutex 构造函数。

其中一位在这里:

m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")()

您传递的字符串参数是共享内存中对象的名称,但它不会传递给实际对象的构造函数,在本例中为 named_mutex。所以这基本上导致调用 named_mutex 的默认构造函数,它是私有的。要将参数传递给底层对象的构造函数,您必须像这样发送它们:

m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name")

在第二组括号中。

第二个问题从同一行开始:

m_oSetFileMutex = make_unique<named_mutex>( m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name") );

这基本上等同于:

named_mutex *temp = m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name") );
m_oSetFileMutex = make_unique<named_mutex>(temp);

您已经有一个指向 named_mutex 的原始指针,您正在将其传递给 make_unique。这导致 make_uniquenamed_mutex* 作为参数调用 named_mutex 的构造函数。这样的构造函数不存在。