Cast from void* to base class virtual function problem

Discussion in 'C++' started by Luke Dalessandro, Sep 18, 2005.

  1. Code: Thread -> U
    -> T

    public class Thread {
    protected:
    thread_t _tid;
    virtual void foo() = 0;

    public:
    // Static entry function for the internal thread
    static void* ThreadEntry(void* pThread) {
    Thread* thread = static_cast<Thread*>(pThread);

    // ***
    // *** This is the error, calls the pure virtual version...?
    // ***
    thread->foo();
    return 0;
    }

    // Starts the internal thread running
    void Start() {
    pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    }
    }

    public class T : public Thread {
    protected:
    virtual void foo() {
    cout << "I'm a T";
    }
    }

    public class U : public Thread {
    protected:
    virtual void foo() {
    cout << "I'm a U";
    }
    }

    As you can see I'm just trying to re-use some pthread code for a
    multithreaded server that spawns new threads for different reasons. I
    can't figure out how to cast the void* to a base Thread* pointer and
    call the pure virtual "foo" function and get the derived behavior...

    Of course, the standard usage like

    Thread* u = new U();
    u->foo();

    calls the derived foo like I expect.

    I also tried a non-pure virtual foo and the Thread::foo is still getting
    called after the cast.

    I'm on OSX 10.4 development version. Not sure which gcc it is.

    Thanks in advance,
    Luke
     
    Luke Dalessandro, Sep 18, 2005
    #1
    1. Advertising

  2. Luke Dalessandro

    Greg Guest

    Luke Dalessandro wrote:
    > Code: Thread -> U
    > -> T
    >
    > public class Thread {
    > protected:
    > thread_t _tid;
    > virtual void foo() = 0;
    >
    > public:
    > // Static entry function for the internal thread
    > static void* ThreadEntry(void* pThread) {
    > Thread* thread = static_cast<Thread*>(pThread);
    >
    > // ***
    > // *** This is the error, calls the pure virtual version...?
    > // ***
    > thread->foo();
    > return 0;
    > }
    >
    > // Starts the internal thread running
    > void Start() {
    > pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    > }
    > }
    >
    > public class T : public Thread {
    > protected:
    > virtual void foo() {
    > cout << "I'm a T";
    > }
    > }
    >
    > public class U : public Thread {
    > protected:
    > virtual void foo() {
    > cout << "I'm a U";
    > }
    > }



    > As you can see I'm just trying to re-use some pthread code for a
    > multithreaded server that spawns new threads for different reasons. I
    > can't figure out how to cast the void* to a base Thread* pointer and
    > call the pure virtual "foo" function and get the derived behavior...
    >
    > Of course, the standard usage like
    >
    > Thread* u = new U();
    > u->foo();
    >
    > calls the derived foo like I expect.
    >
    > I also tried a non-pure virtual foo and the Thread::foo is still getting
    > called after the cast.
    >
    > I'm on OSX 10.4 development version. Not sure which gcc it is.
    >
    > Thanks in advance,
    > Luke


    The code that allocates the Thread object for each pthread created is
    missing from your post. In fact there is no obvious execution order to
    the code that was posted.

    Without knowing what pThread is actually pointing to, it's not possible
    to fully diagnose the problem. It's also possible that there is no code
    in the program to create new Thread objects, in which case the same
    pThread pointer is being passed to every pthread.

    Greg
     
    Greg, Sep 18, 2005
    #2
    1. Advertising

  3. Luke Dalessandro

    Axter Guest

    Luke Dalessandro wrote:
    > Code: Thread -> U
    > -> T
    >
    > public class Thread {
    > protected:
    > thread_t _tid;
    > virtual void foo() = 0;
    >
    > public:
    > // Static entry function for the internal thread
    > static void* ThreadEntry(void* pThread) {
    > Thread* thread = static_cast<Thread*>(pThread);
    >
    > // ***
    > // *** This is the error, calls the pure virtual version...?
    > // ***
    > thread->foo();
    > return 0;
    > }
    >
    > // Starts the internal thread running
    > void Start() {
    > pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    > }
    > }
    >
    > public class T : public Thread {
    > protected:
    > virtual void foo() {
    > cout << "I'm a T";
    > }
    > }
    >
    > public class U : public Thread {
    > protected:
    > virtual void foo() {
    > cout << "I'm a U";
    > }
    > }
    >
    > As you can see I'm just trying to re-use some pthread code for a
    > multithreaded server that spawns new threads for different reasons. I
    > can't figure out how to cast the void* to a base Thread* pointer and
    > call the pure virtual "foo" function and get the derived behavior...
    >
    > Of course, the standard usage like
    >
    > Thread* u = new U();
    > u->foo();
    >
    > calls the derived foo like I expect.
    >
    > I also tried a non-pure virtual foo and the Thread::foo is still getting
    > called after the cast.
    >
    > I'm on OSX 10.4 development version. Not sure which gcc it is.
    >
    > Thanks in advance,
    > Luke


    In C++, you don't put key word public before a class declaration.
     
    Axter, Sep 18, 2005
    #3
  4. Greg wrote:
    > Luke Dalessandro wrote:
    >
    >>Code: Thread -> U
    >> -> T
    >>
    >>public class Thread {
    >> protected:
    >> thread_t _tid;
    >> virtual void foo() = 0;
    >>
    >> public:
    >> // Static entry function for the internal thread
    >> static void* ThreadEntry(void* pThread) {
    >> Thread* thread = static_cast<Thread*>(pThread);
    >>
    >> // ***
    >> // *** This is the error, calls the pure virtual version...?
    >> // ***
    >> thread->foo();
    >> return 0;
    >> }
    >>
    >> // Starts the internal thread running
    >> void Start() {
    >> pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    >> }
    >>}
    >>
    >>public class T : public Thread {
    >> protected:
    >> virtual void foo() {
    >> cout << "I'm a T";
    >> }
    >>}
    >>
    >>public class U : public Thread {
    >> protected:
    >> virtual void foo() {
    >> cout << "I'm a U";
    >> }
    >>}

    >
    >
    >
    >>As you can see I'm just trying to re-use some pthread code for a
    >>multithreaded server that spawns new threads for different reasons. I
    >>can't figure out how to cast the void* to a base Thread* pointer and
    >>call the pure virtual "foo" function and get the derived behavior...
    >>
    >>Of course, the standard usage like
    >>
    >> Thread* u = new U();
    >> u->foo();
    >>
    >>calls the derived foo like I expect.
    >>
    >>I also tried a non-pure virtual foo and the Thread::foo is still getting
    >>called after the cast.
    >>
    >>I'm on OSX 10.4 development version. Not sure which gcc it is.
    >>
    >>Thanks in advance,
    >>Luke

    >
    >
    > The code that allocates the Thread object for each pthread created is
    > missing from your post. In fact there is no obvious execution order to
    > the code that was posted.
    >
    > Without knowing what pThread is actually pointing to, it's not possible
    > to fully diagnose the problem. It's also possible that there is no code
    > in the program to create new Thread objects, in which case the same
    > pThread pointer is being passed to every pthread.
    >
    > Greg
    >


    Greg,

    Sorry about the lack, I was trying to remove everything that didn't seem
    necessary. The code is basically:

    int main (int argc, const * char argv[]) {

    string toExit;
    Thread* t;

    while (toExit != "exit") {

    cin >> toExit;

    if (toExit = "U") {
    t = new U();
    }
    else {
    t = new V();
    }

    t->Start();

    delete t;

    }

    }

    Constructors are:

    Thread::Thread() {}
    U::U() {}
    V::V() {}

    Destructors are:

    virtual ~Thread() {}
    virtual ~U() {}
    virtual ~V() {}

    I realize that the main thread s pulling the rug out from under the
    pthreads that are running inside the Thread objects... I'm actually
    storing the pointers somewhere and joining and deleting threads elsewhere.

    Luke
     
    Luke Dalessandro, Sep 18, 2005
    #4
  5. Axter wrote:
    > Luke Dalessandro wrote:
    >
    >>Code: Thread -> U
    >> -> T
    >>
    >>public class Thread {
    >> protected:
    >> thread_t _tid;
    >> virtual void foo() = 0;
    >>
    >> public:
    >> // Static entry function for the internal thread
    >> static void* ThreadEntry(void* pThread) {
    >> Thread* thread = static_cast<Thread*>(pThread);
    >>
    >> // ***
    >> // *** This is the error, calls the pure virtual version...?
    >> // ***
    >> thread->foo();
    >> return 0;
    >> }
    >>
    >> // Starts the internal thread running
    >> void Start() {
    >> pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    >> }
    >>}
    >>
    >>public class T : public Thread {
    >> protected:
    >> virtual void foo() {
    >> cout << "I'm a T";
    >> }
    >>}
    >>
    >>public class U : public Thread {
    >> protected:
    >> virtual void foo() {
    >> cout << "I'm a U";
    >> }
    >>}
    >>
    >>As you can see I'm just trying to re-use some pthread code for a
    >>multithreaded server that spawns new threads for different reasons. I
    >>can't figure out how to cast the void* to a base Thread* pointer and
    >>call the pure virtual "foo" function and get the derived behavior...
    >>
    >>Of course, the standard usage like
    >>
    >> Thread* u = new U();
    >> u->foo();
    >>
    >>calls the derived foo like I expect.
    >>
    >>I also tried a non-pure virtual foo and the Thread::foo is still getting
    >>called after the cast.
    >>
    >>I'm on OSX 10.4 development version. Not sure which gcc it is.
    >>
    >>Thanks in advance,
    >>Luke

    >
    >
    > In C++, you don't put key word public before a class declaration.
    >


    Lol... you're right... I've been stuck in C# land for too long (language
    at work). Thanks for pointing that out... I didn't cut and paste the
    code, I just re-wrote it in simplified form, so there was no compiler
    around to yell at men.

    Luke
     
    Luke Dalessandro, Sep 18, 2005
    #5
  6. Luke Dalessandro wrote:
    >
    >
    > Greg wrote:
    >
    >> Luke Dalessandro wrote:
    >>
    >>> Code: Thread -> U
    >>> -> T
    >>>
    >>> public class Thread {
    >>> protected:
    >>> thread_t _tid;
    >>> virtual void foo() = 0;
    >>>
    >>> public:
    >>> // Static entry function for the internal thread
    >>> static void* ThreadEntry(void* pThread) {
    >>> Thread* thread = static_cast<Thread*>(pThread);
    >>>
    >>> // ***
    >>> // *** This is the error, calls the pure virtual version...?
    >>> // ***
    >>> thread->foo();
    >>> return 0;
    >>> }
    >>>
    >>> // Starts the internal thread running
    >>> void Start() {
    >>> pthread_create(&_tid, NULL, Thread::ThreadEntry, this);
    >>> }
    >>> }
    >>>
    >>> public class T : public Thread {
    >>> protected:
    >>> virtual void foo() {
    >>> cout << "I'm a T";
    >>> }
    >>> }
    >>>
    >>> public class U : public Thread {
    >>> protected:
    >>> virtual void foo() {
    >>> cout << "I'm a U";
    >>> }
    >>> }

    >>
    >>
    >>
    >>
    >>> As you can see I'm just trying to re-use some pthread code for a
    >>> multithreaded server that spawns new threads for different reasons. I
    >>> can't figure out how to cast the void* to a base Thread* pointer and
    >>> call the pure virtual "foo" function and get the derived behavior...
    >>>
    >>> Of course, the standard usage like
    >>>
    >>> Thread* u = new U();
    >>> u->foo();
    >>>
    >>> calls the derived foo like I expect.
    >>>
    >>> I also tried a non-pure virtual foo and the Thread::foo is still getting
    >>> called after the cast.
    >>>
    >>> I'm on OSX 10.4 development version. Not sure which gcc it is.
    >>>
    >>> Thanks in advance,
    >>> Luke

    >>
    >>
    >>
    >> The code that allocates the Thread object for each pthread created is
    >> missing from your post. In fact there is no obvious execution order to
    >> the code that was posted.
    >>
    >> Without knowing what pThread is actually pointing to, it's not possible
    >> to fully diagnose the problem. It's also possible that there is no code
    >> in the program to create new Thread objects, in which case the same
    >> pThread pointer is being passed to every pthread.
    >>
    >> Greg
    >>

    >
    > Greg,
    >
    > Sorry about the lack, I was trying to remove everything that didn't seem
    > necessary. The code is basically:
    >
    > int main (int argc, const * char argv[]) {
    >
    > string toExit;
    > Thread* t;
    >
    > while (toExit != "exit") {
    >
    > cin >> toExit;
    >
    > if (toExit = "U") {
    > t = new U();
    > }
    > else {
    > t = new V();
    > }
    >
    > t->Start();
    >
    > delete t;
    >
    > }
    >
    > }
    >
    > Constructors are:
    >
    > Thread::Thread() {}
    > U::U() {}
    > V::V() {}
    >
    > Destructors are:
    >
    > virtual ~Thread() {}
    > virtual ~U() {}
    > virtual ~V() {}
    >
    > I realize that the main thread s pulling the rug out from under the
    > pthreads that are running inside the Thread objects... I'm actually
    > storing the pointers somewhere and joining and deleting threads elsewhere.
    >
    > Luke


    Sigh...

    I think I solved my own problem. I really was deleting the Thread object
    while it's internal thread was still running. This was causing the "pure
    virtual function call" because "this" (passed as a void*) had actually
    been deleted, so casting it to a Thread didn't cast it to a U or a V.

    If I'm more careful about the delete call, ie joining first or
    something, it works fine. Multithreading gets me again...

    Sorry to bother everyone.

    Luke
     
    Luke Dalessandro, Sep 18, 2005
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ollej Reemt
    Replies:
    7
    Views:
    543
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    791
    The Real OS/2 Guy
    Oct 28, 2003
  3. Replies:
    5
    Views:
    842
    S.Tobias
    Jul 22, 2005
  4. Abhishek
    Replies:
    12
    Views:
    807
    Eric Sosman
    Jan 30, 2006
  5. Replies:
    1
    Views:
    413
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page