c++ - 通过返回 front() 和 pops() 的函数清空 std::queue

标签 c++ memory-management destructor

我正在编写一个模板类,它应该提供一个队列来防止并发访问,基本上是为了能够编写可以处理具有可变数量的并发工作线程的项目列表的类。

模板类有一个方法:

bool getFront(T &value)
{ CritSectEx::Scope scope(listLock);
  bool ret = false;
    if( !itemList.empty() ){
        value = itemList.front();
        itemList.pop();
        ret = true;
    }
    return ret;
}

它锁定队列,如果它不为空,则获取第一个元素,将其弹出并返回 true,以便每个工作人员都可以做

    while( getFront(entry) ){
        // do something with entry
        nTreated += 1;
    }
    // exit worker

问题是:我通过 value 引用返回的究竟是什么?当我测试这段代码时,我得到了一个双重释放错误,因为我正在使用的类型 T 包含一个指针(我们称之为 B),它在它的 dtor 中被删除(当 B 没有被标记为指向全局结构的指针)。在 getFront() 中的 pop() 期间调用了 dtor,这似乎合乎逻辑。我注意类型 T 的 ctors 在从现有实例创建新 T 时都会分配 B 的拷贝,并且它不会子类化任何可以提供“=”运算符的东西,所以我不确定我会如何结束T 的 2 个实例,每个实例都包含相同的 B 值和“我们拥有 B”成员。

我做这种事情的次数不够多,所以我可能忽略了这里的一些东西,但是什么?有什么解决此问题的建议吗?

附加观察:似乎总是从队列中弹出的最后一个元素显示此行为。

为了不那么含糊,下面是我对类型名 T 的使用:

struct folder_info
{
    // plenty of members snipped
#ifdef __cplusplus
public:
    folder_info()
    {
        memset( this, 0, sizeof(struct folder_info) );
    }
    folder_info(const struct folder_info *src)
    {
        init(src);
    }
    folder_info(const struct folder_info &src)
    {
        init(&src);
    }
private:
    void init(const struct folder_info *src)
    {
        memcpy( this, src, sizeof(struct folder_info) );
        // we don't duplicate the filetypeslist!
        filetypeslist = NULL;
        filetypeslistlen = filetypeslistsize = 0;
    }
#endif
};

typedef struct FileEntry {
public:
    std::string fileName;
    struct stat fileInfo;
    FolderInfo *folderInfo;
    bool freeFolderInfo;
    FileEntry();
    FileEntry( const char *name, const struct stat *finfo, FolderInfo *dinfo, const bool ownInfo=false );
    FileEntry( const char *name, const struct stat *finfo, FolderInfo &dinfo );
    FileEntry(const FileEntry &ref);
    ~FileEntry();
} FileEntry;

FileEntry::FileEntry()
{
    folderInfo = NULL;
    freeFolderInfo = false;
}

FileEntry::FileEntry( const char *name, const struct stat *finfo, FolderInfo *dinfo, const bool ownInfo )
{
    fileName = name;
    fileInfo = *finfo;
    folderInfo = (ownInfo)? new FolderInfo(dinfo) : dinfo;
    freeFolderInfo = ownInfo;
}

FileEntry::FileEntry( const char *name, const struct stat *finfo, FolderInfo &dinfo )
{
    // creating a FileEntry with a FolderInfo reference always makes a copy
    // of the FolderInfo structure
    FileEntry( name, finfo, new FolderInfo(dinfo), true );
}

FileEntry::FileEntry(const FileEntry &ref)
{
    fileName = ref.fileName;
    fileInfo = ref.fileInfo;
    if( ref.freeFolderInfo ){
        folderInfo = new FolderInfo(ref.folderInfo);
    }
    else{
        folderInfo = ref.folderInfo;
    }
    freeFolderInfo = ref.freeFolderInfo;
}

FileEntry::~FileEntry()
{
    if( freeFolderInfo && folderInfo ){
        delete folderInfo;
        folderInfo = NULL;
    }
}

最佳答案

如果我做对了,问题是 FileEntry 缺少用户定义的赋值运算符。

如果复制的 FileEntryfreeFolderInfo ==,你的复制构造函数会处理每个 FileEntry 都有一个新的 FolderInfo true,而您的赋值运算符不是。

如果您将一个 FileEntry 分配给另一个,并且如果两者都有 freeFolderInfo == true,您将删除同一个指针两次,一旦最后一个两个超出范围/被删除。

What is The Rule of Three?

If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.

关于c++ - 通过返回 front() 和 pops() 的函数清空 std::queue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30557632/

相关文章:

c++ - 从 C++ xll 返回多维数组到 excel

在最大堆中分配字节 [] 时出现 Java OutOfMemoryError

C++ 和析构函数(嵌套类和一般问题)

c++ - 你能显式地使用祖先的虚类方法作为派生方法吗?

c++ - 哪里需要(不需要)完整类型?

c++ - 了解 C++ 程序 [ Bjarne Stroustrup 的书 ]

java - 链表可以存储不同的数据类型吗?

cocoa - NSPredicate 内存问题

c++ - 默认析构函数有作用吗?

c++ - 包含所述对象 vector 的对象的析构函数