我目前正在开发一个包含计时器的 SDL_Project。 SDL_Timer 可以有一个回调函数,并且由于我的计时器位于一个类中,因此该回调函数是一个静态成员函数,我通过 void* 参数将“this”传递给它。
但是类还有另一个成员变量,它是指针。但是一旦我调用回调函数,这些指针就不再有效。我想这有点道理,因为静态函数是在另一个线程中调用的。
有办法解决这个问题吗?我对多线程不太熟悉,所以我不知道要寻找什么。
这是我正在做的事情的基本表示,尽管这个例子工作得很好,因为如果我的理论是正确的话,它都在一个线程中。
//A is just an interface so that B can hold a pointer to it
class A
{
public:
virtual int get() = 0;
};
class C
{
public:
C(){};
C(A* parent_arg)
{
parent = parent_arg;
}
void (*fptr)(C* sender) = nullptr;
static void callback(void* param)
{
//In my actual program, me has lost its parent pointer
C* me = (C*)param;
me->fptr(me);
};
//In my actual code, this function is from a SDL_Timer and
//runs in another thread
void Go()
{
callback(this);
}
A* parent = nullptr;
};
class B : A
{
public:
B()
{
c.parent = this;
};
virtual int get() { return myint; };
C c;
private:
int myint = 5;
};
void myfun (C* sender)
{
std::cout << sender->parent->get() << "\n";
};
int _tmain(int argc, _TCHAR* argv[])
{
B b;
b.c.fptr = myfun;
b.c.Go();
int test;
std::cin >> test;
return 0;
}
编辑:
这里有更多关于 C 和 B 创建后我如何处理它们以及它们如何在实际程序中实现的信息。 所有涉及的类都是可复制构造的。而B中的成员变量c是在一个boost::stable_vector中。由于对于其他任务来说这一切都工作正常,因此我假设我的复制构造函数和赋值运算符都可以。 如果我在回调中检查 me 的值,结果发现 me 本身仍然保留了除指针之外的所有值。
编辑2:
我发现问题了。我复制B对象时没有更新父指针。谢谢大家的帮助。
您提供的信息太少,无法确定地回答您。最有可能的是,在从另一个线程调用
b
之前,对象 callback
被销毁(可能是从创建它的线程中)。
向
class B
添加带有一些日志记录的析构函数。在 C::callback()
的开头添加一些日志记录,这会给你一个提示发生了什么。另外,向 A
添加一个虚拟析构函数,如果您有类似 A* a = new B(); delete a;
之类的东西,这一点至关重要。
如果您无法通过手动代码审查来检测问题,请使用 valgrind memcheck/helgrind 来帮助您检测任何潜在的内存损坏问题。
也许使您的类成为单例或使整个类静态,这样您就可以将成员函数作为常规函数指针传递。静态成员函数指针不需要通过对象指针调用。我知道这个问题已经很老了,以防万一有人偶然发现这个问题。