LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Problem with passing a class address to a thread (https://www.linuxquestions.org/questions/programming-9/problem-with-passing-a-class-address-to-a-thread-602242/)

nalsrayatko 11-25-2007 08:50 AM

Problem with passing a class address to a thread
 
Hi all;

I am newbie to the concept of thread programming, and I have written a simple program trying to pass multiple parameters(includes calling class address) to a thread. But it gives me 'Segmentation fault' error, when I try to change the class attributes. I don't understand what the problem is. However, when I call sleep(1) function after creation of the thread, it runs normally. It seems a synchronization problem between thread and creating program. But I really don't understand what reasons that causes synchronization problem are. Does anybody know about the problem? (Eclipse 3.2.2, Fedora Core 6)


Thanks for everything
Yatko Nalsra


Code:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>


void*
Loop(void* arg);

class Student
{
public:
    Student();
    void Start();

protected:
    int number;
    friend void* Loop(void*);
};

int main()
{
    Student victor;
 
    victor.Start();
 
    sleep(14);
    printf("The End\n");
}


struct param
{
    int number;
    Student* ptr;
};

Student::Student()
{}

void
Student::Start(void)
{
    pthread_attr_t attr;
    pthread_attr_init( &attr );
    pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
 
    param temp;
    temp.number = 10;
    temp.ptr = this;
 
    pthread_t handle;
 
    int error;
    error = pthread_create( &handle, &attr,&Loop, &temp );
 
    //sleep(1); when I call this function, it runs perfect.

    if (error)
        return;

}

void*
Loop(void* arg)
{
    param *temp = (param *)arg;
 
    int number = temp->number;
    Student& ptr = *(temp->ptr);
    ptr.number = number;  // When I try to change class attributes, it causes 'segmentation fault' error.
 
    for(int i = 0; i < 10 ;++i){
        printf("number :  %d loop:%d \n", ptr.number,i);
        sleep(2);
 
    }
}


ta0kira 11-25-2007 11:08 AM

The reason it works with sleep is because that pauses the execution of the calling function while the thread catches up. Without sleep the Start function exits before the thread assigns ptr, making temp no longer exist when the thread tries to use it via the handle (Student& ptr = *(temp->ptr);.)
ta0kira

PS Because the stack unwinds after the return of Start and temp was the second item placed on its stack, it's likely already overwritten by the sleep(14) call before the thread gets to it.

PPS If the Student class creates the thread then it needs to store a pthread_t as a class member. In the destructor, it either needs to pthread_cancel or pthread_wait so that the thread is never running when the object no longer exists. The sleep(14) mitigates this for you, but it's highly unrealistic because that defeats the purpose of a thread.

P^3S Some advice for your future in multi-threading (doesn't apply here, but can save you a headache):
Code:

//instead of:
int *my_int = new int;
delete my_int;
my_int = NULL;

Code:

//do this to prevent a gap (or exception) between 'delete' and '= NULL'
int *my_int = new int;
int *temp = my_int;
my_int = NULL;
delete temp;


nalsrayatko 11-25-2007 11:59 AM

Thanks very much ta0kira.

I see the problem now, clearly and I have changed my code. In the new code, after the creation of thread, the Start() function waits on a boolean (threadRunning) variable until the thread set it as true. Also, thanks for your other advices and I hope to learn more things from this forum.

Yatko


All times are GMT -5. The time now is 07:36 AM.