2014-10-05 79 views
0

我目前正在处理包含定时器的SDL_Project。 SDL_Timer可以有一个回调函数,并且由于我的计时器位于一个类中,所以此回调函数是一个静态成员函数,我通过void * -argument传递“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中。由于其他任务,这一切工作正常,我假设我的复制构造函数和赋值运算符都可以。 如果我在回调中检查了我的值,事实证明,除了指针之外,我本身仍然具有所有的值。

编辑2:

我发现了这个问题。当我复制B对象时,我没有更新父指针。感谢大家的帮助。

+0

在创建线程时如何将成员函数绑定到它的实际实例? – 2014-10-05 16:05:27

+0

你是不是这个意思? 'std :: function t = std :: bind(this-> callback,std :: placeholders :: _ 1,std :: placeholders :: _ 2); l_timer = SDL_AddTimer(l_delay,t,this);'?在这里我得到一个“无法从SDL_Callback转换为std :: function”的错误。 – LordOfThunder123 2014-10-05 16:09:16

+0

'SDL_Callback'是否允许用户定义'void *'额外参数?否则机会很低,要把它绑定到一个特定的类实例上,它的成员函数应该在线程中调用。 – 2014-10-05 16:15:53

回答

0

您提供的信息太少,难以确定地回答您。在另一个线程调用callback之前,很有可能对象b被破坏(可能来自它创建的线程)。

添加一个日志记录到class B的析构函数。在C::callback()的开头添加一些日志记录,这会给你提示发生了什么。此外,添加一个虚拟析构函数到A,这对于你有类似A* a = new B(); delete a;的东西至关重要。

0

如果您无法通过手动代码审查检测问题,请使用valgrind memcheck/helgrind来帮助您检测任何潜在的内存损坏问题。