问题描述
EDIT:SOLVED
我正在开发一个多线程项目,现在我有一个基本工作类,从它继承的工作类。在运行时,工作者类成为线程,然后根据需要执行工作。
I'm working on a multi-threaded project right now where I have a base worker class, with varying worker classes that inherit from it. At runtime, the worker classes become threads, which then perform work as needed.
现在,我有一个导演我写的应该维护一个指针数组
Now, I have a Director I've written which is supposed to maintain an array of pointers to all of the workers, so that it can retrieve information from them, as well as modify variables within them later.
我这样做是通过创建一个指向指针的指针。基类:
I did this by creating a pointer to a pointer of the base class:
baseWorkerClass** workerPtrArray;
然后在Director的构造函数中,我动态地为基本工作类分配一个指针数组:
Then in the constructor of the Director, I dynamically allocate an array of pointers to the base worker class:
workerPtrArray = new baseWorkerClass*[numWorkers];
在每个工作线程的构造函数中,worker调用导向器中的一个函数,
In the constructor of each worker thread, the worker calls a function in the director which is meant to store the pointer of that worker in the array.
以下是导演存储指针的方法:
Here's how the director stores the pointers:
Director::manageWorker(baseWorkerClass* worker)
{
workerPtrArray[worker->getThreadID()] = worker;
}
这里是一个工作变量的例子。每个工作程序都继承基本工作类,基类工作类包含纯虚函数,它应该存在于所有工作变量中,以及所有工作者之间共享的一些变量。
Here is an example of a worker variant. Each worker inherits from the base worker class, and the base worker class contains pure virtual functions which should exist in all worker variants, as well as a few variables which are shared between all workers.
class workerVariant : protected baseWorkerClass
{
public:
workerVariant(int id)
: id(id)
{
Director::manageWorker(this);
}
~workerVariant()
{
}
int getThreadID()
{
return id;
}
int getSomeVariable()
{
return someVariable;
}
protected:
int id;
int someVariable
};
然后baseWorkerClass看起来像这样:
Then the baseWorkerClass looks something like this:
class baseWorkerClass
{
public:
baseWorkerClass()
{
}
~baseWorkerClass()
{
}
virtual int getThreadID() = 0;
virtual int getSomeVariable() = 0;
};
在每个工作变量完成初始化后,我最终会得到一个指向baseWorkerClass对象的指针数组。这意味着我应该能够,例如,使用它的ID作为数组的索引,在某个工人中获取给定变量的值,如下:
After each worker variant is done initializing, I should end up with an array of pointers to baseWorkerClass objects. This means I should be able to, for example, get the value of a given variable in a certain worker using its ID as the index to the array, like so:
workerPtrArray[5]->getSomeVariable(); // Get someVariable from worker thread 5
问题是这个代码导致Windows可执行文件崩溃,没有任何解释为什么,在Linux中,它说:
The problem is that this code causes a crash in a Windows executable, without any explanation of why, and in Linux, it says:
我可以宣誓我在某个时候工作了,
I could've sworn I had this working at some point, so I'm confused as to what I've screwed up.
遇到问题的实际未修改代码:
Actual unmodified code that has the problem:
工人变体标题:
工作变量源文件:
基本工作者类标题:
基本工作者类源文件:
Base worker class header: http://pastebin.com/f2effac5
Base worker class source file: http://pastebin.com/f3506095b
导演标题:
导演来源档案:
编辑:额外的信息,在manageWorker函数中,我可以从指针worker调用任何纯虚函数,它工作正常。除了manageWorker函数,当我尝试使用指针数组时,它失败。
Extra information, in the manageWorker function, I can call any of the pure virtual functions from the pointer "worker," and it works just fine. Outside of the manageWorker function, when I try to use the pointer array, it fails.
编辑:现在我想想,线程的入口点是operator 。 Director线程在工人之前创建,这可能意味着重载的括号运算符在它们可以被子类覆盖之前调用纯虚函数。我正在研究这个。
Now that I think about it, the thread's entry point is operator(). The Director thread is created before the workers, which may mean that the overloaded parenthesis operator is calling pure virtual functions before they can be overridden by the child classes. I'm looking into this.
推荐答案
问题似乎是 Director :: manageWorker
在
workerVariant
实例的构造函数中调用:
The problem appears to be that Director::manageWorker
is called in the constructor of workerVariant
instances:
Director::manageWorker(baseWorkerClass* worker) {
workerPtrArray[worker->getThreadID()] = worker;
}
可能 getThreadID()
不是一个纯虚函数,或者你会有(希望!)得到一个编译器错误,没有覆盖它在 workerVariant
。但 getThreadID()
可能会调用其他函数,你应该重写,但是在抽象类中被调用。你应该仔细检查 getThreadID()
的定义,以确保你没有做任何不正常,这将取决于子类正确初始化之前。
Presumably getThreadID()
isn't a pure virtual function or you would have (hopefully!) gotten a compiler error about not overriding it in workerVariant
. But getThreadID()
might call other functions which you should override, but are being invoked in the abstract class. You should double check the definition of getThreadID()
to make sure you're not doing anything untoward that would depend on the child class before it's properly initialized.
一个更好的解决方案是将这种多阶段初始化分离成一个单独的方法,或者设计 Director
和 baseWorkerClass
,这样他们没有这种初始化时间的相互依赖性。
A better solution might be to separate this sort of multi-stage initialization into a separate method, or to design Director
and baseWorkerClass
such that they don't have this sort of initialization-time interdependency.
这篇关于纯虚拟方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!