2012-03-30 5 views
2

Nun, ich versuche, eine Variable in einem Thread verwenden, funktioniert es gut, wenn ich den PThread von der Hauptfunktion aufrufen, aber wenn ich anrufe es aus einer Funktion oder einer Funktion innerhalb einer Klasse, wird die Variable verloren und druckt statt Müll, das ist, warum ich die BedingungPthread Zugriff auf es von einer Klasse, Variablen verloren gehen, wenn direkt funktioniert

if(this->pickup < 7)

so habe ich den Code so minimiert ich es hier posten könnte, weil es alle Beispiele hat Ich sage.

Der Ausgang dieses Code unten:

Access by Class:

Hello, world! <

Access Directly:

Hello, world!, N: 6<

ich wie in Access das gleiche Ergebnis haben möchte direkt in Access von der Klasse, ich will es zur Ausgabe des“N: 6" , weil nach alles wurde definiert. Was fehlt mir hier?

Ich hoffe, ich war klar genug, danke im Voraus.

(By the way, ich bin die pthread-Bibliothek, die für Windows verfügbar ist) so hier ist der Code:

#include <stdio.h> 
#include <pthread.h> 
#include <iostream> 
#include <conio.h> 
#include <windows.h> 

class C { 
public: 
    int pickup; 

    void *hello() 
    { 
     std::cout << "\nHello, world!"; 

     if(this->pickup < 7) 
     std::cout << ", N: " << this->pickup; 

     std::cout << "<" << std::endl; 
     printf("HI"); 
     return 0; 
    } 

    static void *hello_helper(void *context) 
    { 
     return ((C *)context)->hello(); 
    } 


    void StartThread(){ 
     C c; 
     c.pickup = 6; 

     pthread_t t; 
     pthread_create(&t, NULL, &C::hello_helper, &c); 
    } 


}; 



int main() { 

    C c; 
    std::cout << "Access by Class: \n"; 
    c.StartThread(); 
    c.pickup = 6; 
    Sleep(2000); 

    std::cout << "\nAccess Directly: \n"; 
    pthread_t t; 
    pthread_create(&t, NULL, &C::hello_helper, &c); 

    _getch(); 
    return 0; 
} 

Antwort

2

c zerstört wird, wenn StartThread() zurückkehrt, ist hello_helper() bedeutet einen baumelnden Zeiger mit was zu undefiniertem Verhalten führt.

Wechseln zu:

void StartThread(){ 
    C* c = new C(); 
    c->pickup = 6; 

    pthread_t t; 
    pthread_create(&t, NULL, &C::hello_helper, c); 
} 

das Argument in hello_helper() weitergegeben delete Denken Sie daran:

static void *hello_helper(void *context) 
{ 
    C* c = static_cast<C*>(context); 
    c->hello(); 
    delete c; 
    return 0; 
} 

EDIT:

immer delete das Argument in hello_helper() geben ing würde verhindern Stapel zugeordneten Objekte vorbei in hello_helper(). Ein Mechanismus ist erforderlich, um hello_helper() anzuweisen, ob er für die Zerstörung seines Arguments verantwortlich ist.

+0

hm Wie könnte ich das beheben? – Grego

+0

@Grego, aktualisierte Antwort. – hmjd

+0

es noch Müll gedruckt, ging es Hallo, Welt !, N: -17891602 – Grego

0

Der Aufruf an pthread_create() kehrt sofort zurück, daher verlassen Sie die Funktion C::StartThread, bevor Ihr erstellter Thread wirklich eine Chance hat, ausgeführt zu werden. Somit existiert das C Instanzobjekt, das durch c repräsentiert wird, nicht mehr, da es eine automatische Variable auf dem Stapel von StartThread war. Sie müssen sicherstellen, dass die Lebensdauer von c über den Stapel von StartThread existiert, die typischerweise dynamische Speicher durchgeführt wird, oder möglicherweise eine statische Variable usw.

1

Die C Sie fangen den Faden mit in StartThread() geht außerhalb des Geltungsbereichs und wird zerstört, bevor der Thread, den Sie erstellen, eine Chance hat, ihn zu verwenden.

Wenn Sie die Instanz der Klasse wissen, dass Sie StartThread() auf Aufruf wird für die gesamte Lebensdauer des Themas existieren, vielleicht wollen Sie this als Kontext passieren, anstatt ein neues Stapelobjekt:

void StartThread() { 
    pthread_t t; 
    pthread_create(&t, NULL, &C::hello_helper, this); 
} 
+0

Könnten Sie mir ein Beispiel in der Codezeile geben? – Grego

+0

hmm das wusste ich, das hat funktioniert, aber ich möchte die Variable innerhalb der Funktion statt außerhalb definieren. Als ob ich C c gemacht hätte; \t \t c.pickup = 6; innerhalb des StartThread – Grego

+0

Dann sollte StartThread statisch sein. Es gibt keinen Grund, ein 'C' in main zu erstellen, nur um StartThread aufzurufen, damit es ein anderes' C' erstellen kann, um den Thread zu starten. – Collin

0

Beachten Sie, dass StartThread erstellt ein C Objekt, das weder aus einem beliebigen Argumentmaterial (StartThread keine Argumente enthält) noch aus einem Mitgliedsmaterial der Klasse, von dem StartThread ein Mitglied ist. Das heißt Sie diese haben können:

void StartThread(){ 
    pthread_t t; 
    pthread_create(&t, NULL, &C::hello_helper, NULL); 
} 

// The code is easily moved into the thread. 
static void hello_helper(void *) 
{ 
    C c; 
    c.pickup = 6; 

} 

Des Weiteren ist es möglich, dass Sie das eigentlich wollte?

void StartThread(){ 
    pthread_t t; 
    pickup = 6; 
    // use THIS object, not some new one, doh? 
    pthread_create(&t, NULL, &C::hello_helper, (void *) this); 
} 

I.e. vielleicht wollen Sie eigentlich obj.StartThread() einen Thread, der mit obj arbeitet, anstatt ein anderes Objekt intern erstellen?

Verwandte Themen