【发布时间】:2015-08-13 23:25:31
【问题描述】:
我正在编写一个模板类,它应该提供一个防止并发访问的队列,基本上是为了能够编写可以处理具有可变数量的并发工作线程的项目列表的类。
模板类有一个方法:
bool getFront(T &value)
{ CritSectEx::Scope scope(listLock);
bool ret = false;
if( !itemList.empty() ){
value = itemList.front();
itemList.pop();
ret = true;
}
return ret;
}
锁定队列,如果不为空则取出第一个元素,弹出并返回true,这样每个worker都可以做
while( getFront(entry) ){
// do something with entry
nTreated += 1;
}
// exit worker
问题是:我通过value 引用返回这里到底是什么?当我测试这段代码时,我得到一个双重释放错误,因为我使用的类型 T 包含一个指针(我们称之为 B),该指针在其 dtor 中被删除(当 B 未标记为指向全局结构的指针时) )。该 dtor 已在 getFront() 中的 pop() 期间被调用,这似乎是合乎逻辑的。我注意到类型 T 的 ctor 在从现有实例创建新 T 时都分配了 B 的副本,并且它不会子类化任何可以提供“=”运算符的东西,所以我不确定我会如何结束2 个 T 实例,每个实例都包含相同的 B 值和“我们拥有 B”成员。
我不经常做这种事情,所以我可能在这里忽略了一些东西,但是什么?有什么建议可以解决这个问题吗?
补充观察:似乎总是从队列中弹出的最后一个元素显示此行为。
为了不那么模糊,这里是我使用的 typename 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;
}
}
【问题讨论】:
-
您能尝试创建一个Minimal, Complete, and Verifiable Example 并展示给我们看吗?请不要在 cmets 中发布重要信息(尤其不是代码),请编辑您的问题以包含此类内容。
-
附加信息有帮助吗?我正在以一种可重用的方式编写此代码,但也已使用特定的应用程序(没有并行方面);提取有问题的代码并将其转换为独立示例需要一些工作。
-
我认为@Joachim 指的是您发布的代码甚至无法编译,因此我们没有机会对其进行测试
-
我对实际问题也有点不清楚。您是在问参数传递,还是关于双释放错误?
-
@JoachimPileborg 他可能有点困惑,正在错误的位置寻找错误的根源。我认为他的问题是分配而不是模板化的引用返回;使问题本质上与资源管理类中缺少分配运算符的一堆相关问题重复。
标签: c++ memory-management destructor