0

I am very surprised by the strange exception, that I got.

class Threads { 
    public:
        Threads() {}
        ~Threads() {}
        void StartThread(int (*p)()); //pointer to a function 
    private: 
        HANDLE hThread; 
        DWORD dwThreadID; 
    }; 

Method StartThread should receive pointer to my function (that will be run in another thread).
This function is simple. (as you can see it is situated outside the class Threads):

int MyThread() 
{
return 0; 
}

And this is method of creating thread:

inline void Threads::StartThread(int (*p)()) 
{
    hThread = CreateThread(NULL, 
            0, 
            (LPTHREAD_START_ROUTINE)(*p)(), 
            NULL,  
            0, 
            &dwThreadID); 

   if (hThread == NULL) 
        {
            return;
        }
}

Here compiler get error: cannot convert parameter 3 from 'int' to 'LPTHREAD_START_ROUTINE'. That why I did the casting.

In main function I create object of type Threads and I try to call method StartThread. As parameter I send pointer to the function MyThread.

Threads *thread1; 
thread1 = new Threads(); 
thread1->StartThread(MyThread);

I thought MyThread must start in another thread. But the function MyTread always runs in Main Thread!!! And only after MyThread ends, another thread starts and then I get this exception: Unhandled exception at 0x00000000 in ThreadClass.exe: 0xC0000005: Access violation.

I need clever advice!

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • 1
    This has been asked many times before: http://stackoverflow.com/questions/1372967/how-to-use-createthread-for-functions-which-are-class-members http://stackoverflow.com/questions/2891926/create-thread-is-not-accepting-the-member-functon http://stackoverflow.com/questions/402992/passing-function-pointers-in-c http://stackoverflow.com/questions/7140042/c-functor-as-a-function-pointer http://stackoverflow.com/questions/4681581/how-do-i-call-worker-thread-in-a-same-class-c-mfc http://stackoverflow.com/questions/4666635/run-threads-of-class-member-function-in-c to name a few – Adam Rosenfield Sep 20 '11 at 18:54

2 Answers2

2

The call convention is wrong:

LPTHREAD_START_ROUTINE is a __stdcall method not a __cdecl method, see the documentation here: http://msdn.microsoft.com/en-us/library/aa964928.aspx.

Kevin
  • 24,871
  • 19
  • 102
  • 158
0

It looks like you are actually calling the function on this line...

(LPTHREAD_START_ROUTINE)(*p)()

...and it returns an int that you're casting. That just can't work. How about:

(LPTHREAD_START_ROUTINE)p 

...instead?

executifs
  • 1,138
  • 1
  • 9
  • 23
  • @Girl_Developer: Just because it looks like it works doesn't mean it does. The function signature is all wrong -- an `LPTHREAD_START_ROUTINE` takes one parameter of type `LPVOID`, returns a `DWORD`, and uses the `__stdcall` calling convention. If you have the function type correct, you do not need and should not use a cast. When your thread routine returns, it's going to crash because the stack is messed up since you got the calling convention wrong. – Adam Rosenfield Sep 20 '11 at 19:24
  • +1 to Adam's comment above; if you're using a cast at all here, you're likely doing it wrong. I don't think there's any case in Win32 where you should ever need to cast a function. Generally casts should be viewed with suspicion. – BrendanMcK Sep 20 '11 at 19:48