c++windowspointersreferencecreatethread

Windows CreateThread within a class function call, pointer reference crash?


Below I have an int main() and two header files, one of which is a class for creating a thread and another which is a class called object that gets created within the windows_thread class. This really simple exercise should output 99 but instead its 1 (for some unknown reason). I also tried using a pointer to an object made by new which crashed when void call() from the function Thread_no_1( ) to the class object is made, maybe because its none existent. I hope someone could remedy this otherwise I'll just use windows threads in int main().

this is the main.

#include "windows_thread.h"

int main()
{
    windows_thread* THREAD = new windows_thread();
    THREAD->thread();

    delete THREAD;

    return 0;
}

this is the windows_thread.h

#include <windows.h>
#include <stdio.h>
#include "object.h"

#define BUF_SIZE 255

class windows_thread
{
        object OBJECT;

    public:

        windows_thread():OBJECT(99)
        {
            //OBJECT = new object(99);

        }
        ~windows_thread()
        {
            //delete OBJECT;
        }
        void thread()
        {
            std::cout<<"void thread: "<<std::endl;
            int Data_Of_Thread_1 = 1;            // Data of Thread 1
            HANDLE Handle_Of_Thread_1 = 0;       // variable to hold handle of Thread 1

            HANDLE Array_Of_Thread_Handles[1];   // Aray to store thread handles

    // Create thread 1.
            Handle_Of_Thread_1 = CreateThread( NULL, 0,  Wrap_Thread_no_1, &Data_Of_Thread_1, 0, NULL);
            if ( Handle_Of_Thread_1 == NULL)  ExitProcess(Data_Of_Thread_1);

    // Store Thread handles in Array of Thread Handles as per the requirement of WaitForMultipleObjects()
            Array_Of_Thread_Handles[0] = Handle_Of_Thread_1;


    // Wait until all threads have terminated.
            WaitForMultipleObjects( 1, Array_Of_Thread_Handles, TRUE, INFINITE);

            printf("Since All threads executed lets close their handles \n");

    // Close all thread handles upon completion.
            CloseHandle(Handle_Of_Thread_1);
        }
        void DisplayMessage (HANDLE hScreen, char *ThreadName, int Data, int Count)
        {
            TCHAR msgBuf[BUF_SIZE];
            size_t cchStringSize;
            DWORD dwChars;

    // Print message using thread-safe functions.
    //StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Executing iteration %02d of %s having data = %02d \n"), Count, ThreadName, Data);
    //StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
            WriteConsole(hScreen, msgBuf, cchStringSize, &dwChars, NULL);
            Sleep(1000);
        }
        DWORD WINAPI Thread_no_1(  )
        {
            std::cout<<"Thread_no_1: "<<std::endl;
            OBJECT.call();
            //OBJECT->call();

            return 0;
        }
        static DWORD WINAPI Wrap_Thread_no_1( LPVOID lpParam )
        {
            std::cout<<"Wrap_Thread_no_1: "<<std::endl;

            windows_thread *self = reinterpret_cast<windows_thread*>(lpParam);
            self->Thread_no_1();

            return 0;
        }
};

next is the object.h

#ifndef OBJECT_H
#define OBJECT_H

#include <iostream>

class object
{
        private:

            int value;

        public:

        object(int value)
        {
            std::cout<<"object::constructor: "<<std::endl;
            this->value = value;
        }
        ~object(){}
        void call()
        {
            std::cout<<"object::call(): begin"<<std::endl;
            std::cout<<value<<std::endl;
            std::cout<<"object::call(): end"<<std::endl;
        }
};
#endif

Solution

  • This function call:

    Handle_Of_Thread_1 = CreateThread(
        NULL, 
        0,  
        Wrap_Thread_no_1, 
        &Data_Of_Thread_1, // <== THIS IS A POINTER TO AN int
        0, 
        NULL
        );
    

    Passes &Data_Of_Thread_1 (a pointer to an int) to CreateThread(). This is the argument that gets eventually passed to Wrap_Thread_no_1().

    Inside that function, you then cast that pointer to a windows_thread* and call a member function through it. This injects Undefined Behavior in your code.

    You probably meant to do this instead:

    Handle_Of_Thread_1 = CreateThread(NULL, 0,  Wrap_Thread_no_1, this, 0, NULL);
    //                                                            ^^^^