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

模板类具有一个方法:

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未标记为指向全局结构的指针时)。该dtor在getFront()的pop()期间被调用,这似乎是合乎逻辑的。我很小心,在从现有实例创建新T时,类型T的ctor都分配了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的用户定义的赋值运算符。

您的副本构造函数要注意以下事实:如果复制的FileEntry具有FolderInfo,则每个FileEntry都有一个新的freeFolderInfo == true,而您的赋值运算符则没有。

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

What is The Rule of Three?

10-04 20:51