pthread funktion problem



  • Storm.Xapek.de schrieb:

    isofiles->begin()

    Danke, habe ich schon geändert, allerdings ist das eigentliche Problem das ich die list als Referenz übergebe, denn der thread wird detached und die referenz geht verloren.

    Wie kann ich die liste beim erstellen des thread übergeben?

    ret=pthread_create(&ftpthread,NULL,&fireFtpScript,files);
    

    funktioniert nicht da:

    cannot convert ‘std::list<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >’ to ‘void*’ for argument ‘4’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’



  • dann nimm eine c-cast und mach aus deiner list* doch einfach ein void*. in fireFtpScript machst du es schließlich in die andere richtung genauso. als code:

    ret=pthread_create(&ftpthread,NULL,&fireFtpScript,(void*)(&files));
    


  • Ich habe es nun mit einem struct versucht:

    ret=pthread_create(&ftpthread,NULL,&fireFtpScript,&struct);

    Allerdings funktioniert das nur wenn der thread nicht detached wird.

    Dummerweise brauche ich ihn detached!

    Es wird ein SegmentationFault ausgelöst wenn er detached wird und in der thread funktion versucht wird auf die struct variablen zuzugreifen.

    Ich glaube das liegt daran das ich die Referenz auf ein struct übergebe!



  • Hier der code, ein SegmentationFault ist das Ergebnis, hat hier jemand hilfe?

    struct thread_data{
    	std::list<std::string> isofiles;
    	std::string task;
    };
    
    static void *fireFtpScript( void *ptr )
    {
    
    	pid_t pid;
    
    	struct thread_data *myda = (struct thread_data *) ptr;
    
    	std::list<std::string> isofiles = myda->isofil;
    
    	std::string name = myda->task;
    
    // code zum Verarbeiten entfernt
    
              pthread_exit((void *) 0);
    
    }
    
    void initFtpThread(std::string tname,std::list<std::string> files){
    
    			pthread_t ftpthread;
    			struct thread_data mydata;
    
    			mydata.isofil=files;
    
    			mydata.task=tname;
    	     int ret;
    	     ret=pthread_create(&ftpthread,NULL,fireFtpScript,&mydata);
    
    	     if(ret==0){
    
    	    	 pthread_detach(ftpthread);
    
    	     }else {
    	    	 cout << "can not detach ftp thread" << endl;
    	     }
    	}
    


  • Hi,

    dein Fehler liegt in der Funktion initFtpThread() Zeile 33.
    Die Variable mydata legst du dort lokal an und übergibst
    der Funktion fireFtpScript() einen Pointer auf diese Variable.
    Die Init-Funktion wird aber zu schnell verlassen, so dass
    die Daten, die der Thread bekommt, nicht mehr vorhanden sind.
    Also folgt daraus ein Seg-Fault.

    Verwende daher soetwas:

    thread_data *mydata = new thread_data;
    

    Gruß mcr



  • ok danke für die Info!

    Der Unterschied ist mir nicht so ganz klar, wenn ich in Zeile 33 der Init Funktion :

    struct thread_data mydata;
    

    mit dieser ersetze:

    thread_data *mydata = new thread_data;
    

    Worin liegt dann der Unterschied wenn sich die Init Funktion beendet ?

    In beiden Fällen wird doch ein Verweis auf den Speicher des structs übergeben.

    Warum sollte es hiermit :

    thread_data *mydata = new thread_data;
    

    keinen SegFault geben wenn sich die Init Funktion beendet?

    Nur zu meinem Verständnis...

    Aktuell habe ich einfach ein sleep(1) nach dem pthread_create eingebaut, was wohl nicht so ganz sauber ist....



  • wenn du es statisch allozierst, also mit

    struct thread_data mydata;
    

    wird sowohl die Variable "mydata" als auch der zugehörige speicher, der zu dieser Variable gehört, gelöscht.
    Bei der dynamischen Allokation mittels new, wird zwar der Zeiger beim Verlassen der Funktion vernichtet, nicht aber der Speicher, auf den der Zeiger verweist.
    Wenn du jetzt die Adresse des statisch allokierten Speichers übergibst und die Funktion wird verlassen, erhältst du einen SegFault, sobald in einem Thread darauf, beispielsweise, erneut zugegriffen wird.
    Im anderen Fall ist der Speicherbereich noch vorhanden nach Verlassen der Funktion, lediglich der Zeiger, den du in der Funktion deklariert hast, ist weg, auf den Speicherbereich hast du noch Zugriff.
    Diesen musst du lediglich zum Beispiel beim Beenden des Threads wieder freigeben.



  • Ich vergaß noch zu erwähnen, dass der Aufruf von pthread_create sich
    ebenfalls ändert.

    Komplett sieht das dann so aus:

    thread_data *mydata = new thread_data;
        mydata->isofiles = files;
        mydata->task     = tname;
        int ret = pthread_create(&ftpthread,NULL,fireFtpScript, mydata);
    

    Es wird der Zeiger mydata direkt übergeben und nicht mehr die Adresse
    von mydata.

    Gruß mcr



  • Super, danke ! Den Speicher wieder freigeben heisst vor dem beenden des Thread via free?

    Allerdings habe ich ja keinen explizit reserviert.

    Würde man am Ende des Thread einfach via sizeof mydata freigeben oder wie sähe das aus?



  • Also in meinem Fall:

    free(ptr );

    [cpp]
    static void *fireFtpScript( void *ptr )
    {

    struct thread_data *myda = (struct thread_data 😉 ptr;

    std::liststd::string isofiles = myda->isofil;

    std::string name = myda->task;

    free(ptr );

    // code zum Verarbeiten entfernt

    pthread_exit((void 😉 0);

    }
    [/cpp]

    Oder wird das anders gemacht?



  • also wenn du den code von mcr übernimmst, hast du da:

    thread_data *mydata = new thread_data;
    

    speicher explizit reserviert. am ende des threads also nach dem letzten zugriff darauf, scheint der richtige zeitpunkt zu sein. du darfst dann aber in deinem hauptthread nach dem start des threads nicht mehr darauf zugreifen.

    freigeben solltest du mittels eines delete (free kann muss aber hier nicht das selbe bewirken) und eines casts bzw. du nutzt den cast aus

    struct thread_data *myda = (struct thread_data *) ptr;
    

    das kannst du dann völlig problemlos einfach mit:

    delete myda;
    

    am ende deines threads freigeben. die new/delete-aufrufe sind threadunabhängig.



  • So danke wie gesagt nochmal für die Informationen ich habe das nochmal geändert hier der code:

    struct thread_data{
    	std::list<std::string> isofiles;
    	std::string task;
    	std::string taskname;
    };
    
    static void *fireFtpScript(void *ptr) {
    
    	std::list<std::string> isofiles;
    	std::string name;
    	std::string tname;
    	std::string ftpcopyfilename;
    	int status;
    	struct thread_data *myda;
    	myda = (struct thread_data *) ptr;
    	isofiles = myda->isofiles;
    	name = myda->task;
    	tname = myda->taskname;
    
    	for (std::list<std::string>::iterator i=isofiles.begin(); i!=isofiles.end(); ++i) {
    
    // entfernt 
    
    	}
    
    	isofiles.clear();
    	delete myda;
    	pthread_exit(0);
    
    }
    
    bool initFtpThread(std::string tname,std::string taname,std::list<std::string> files){
    
    			pthread_t ftpthread;
    			thread_data *mydata = new thread_data;
    			mydata->isofiles=files;
    			mydata->task=taname;
    			mydata->taskname=tname;
    
    	     int ret;
    	     pthread_attr_t attr;
    	     pthread_attr_init(&attr);
    	     pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    
    	     ret=pthread_create(&ftpthread,&attr,fireFtpScript,mydata);
    
    	     pthread_attr_destroy(&attr);
    
    	     if(ret){
    
    	    	  	return false;
    
    	     }else {
    	    	 return true;
    	     }
    
    	}
    

Anmelden zum Antworten