Forum: Compiler & IDEs POSIX Thread und Polymorphie


von Stefan (Gast)


Lesenswert?

Hallo!

Ich habe mir eine einfache Threadklasse gebaut, wie nachstehend, die 
unter Windows (GCC Codeblocks) auch wunderbar funktioniert. Wenn ich den 
gleichen Code versuche auf einem µCLinux-System (ARM11) zu compilieren 
und laufen zu lassen scheint die Applikation an der Stelle 
obj->Execute(); abzustürzen. Hat jemand eine Idee woran das liegen 
könnte?

Stefan
1
#include <iostream>
2
#include <conio.h>
3
#include <pthread.h>
4
#include <windows.h>
5
6
using namespace std;
7
8
class PThread
9
{
10
    private:
11
        pthread_t thread;
12
    public:
13
        virtual void Execute(void) = 0;
14
        PThread(void);
15
};
16
17
static void *execute(void *arg)
18
{
19
    PThread *obj = (PThread*) arg;
20
    obj->Execute();
21
    return 0;
22
}
23
24
PThread::PThread(void)
25
{
26
    pthread_create(&thread, NULL, &execute, this);
27
}
28
29
class MyThread: public PThread
30
{
31
    public:
32
        void Execute(void);
33
};
34
35
void MyThread::Execute(void)
36
{
37
    while (1)
38
    {
39
        cout << "Execute" << endl;
40
        Sleep(1000);
41
    }
42
}
43
44
int main()
45
{
46
    MyThread mythread;
47
    getch();
48
    return 0;
49
}

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> Hat jemand eine Idee woran das liegen
> könnte?

lass dir die Adresse vom Objekt doch mal ausgeben

> PThread *obj = (PThread*) arg;
printf("obj: %p\n", obj );
> obj->Execute();

von Stefan (Gast)


Lesenswert?

1
printf("obj: %p\n", obj );
2
obj->Execute();

Unter µCLinux: 0x92c1a8
Unter Windows: 0x28FF14

von Εrnst B. (ernst)


Angehängte Dateien:

Lesenswert?

hmm... Compiliert
( g++ -Wall -o x -pthread x.cc)
und läuft sowohl auf PC als auch auf Linux@ARMv7

Sicher dass du da denselben Code verwendest?

Mit void*-Casts und Polymorpie (oder gar Mehrfachvererbung) kriegt man 
leicht einen "pure virtual function call" hin...

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> printf("obj: %p\n", obj );
> obj->Execute();
>
> Unter µCLinux: 0x92c1a8
> Unter Windows: 0x28FF14

dann mach mal bitte noch hier eine ausgabe rein, da sollte das gleiche 
rauskommen

printf("obj: %p\n", this );
> pthread_create(&thread, NULL, &execute, this);

von Stefan (Gast)


Lesenswert?

Die Adressen stimmen jeweils überein; Hat der eine Compiler evtl. 
"Polymorphieprobleme"?

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> Die Adressen stimmen jeweils überein; Hat der eine Compiler evtl.
> "Polymorphieprobleme"?

kannst du mal testen was passiert wenn du statt

> pthread_create(&thread, NULL, &execute, this);
einfach

this->Execute();

machst.

von Oliver R. (superberti)


Lesenswert?

Hi,

dass der Code in Windows funktioniert ist wohl eher Zufall. Der Thread 
läuft nämlich schon los, bevor Deine abgeleitete Klasse "MyThread" 
vollständig konstruiert ist. Du kannst an dieser Stelle noch nicht auf 
virtuelle Funktionen der Basisklasse zugreifen, da das Objekt hier noch 
nicht seine Endausprägung kennt. Normalerweise gibt das einen "pure 
virtual function called" Laufzeitfehler.
Schreibe eine Run()-Funktion und lass den Thread nach der Konstruktion 
von "MyThread" loslaufen.

Gruß, Oliver

von Stefan (Gast)


Lesenswert?

>Du kannst an dieser Stelle noch nicht auf
>virtuelle Funktionen der Basisklasse zugreifen

Wenn man genau darüber nachdenkt eigentlich völlig logisch, vielen Dank 
für den Hinweis, ich werde meine Threadklasse umbauen!

Gruß
Stefan

von Oliver R. (superberti)


Lesenswert?

Genaugenommen handelt es sich hierbei um eine klassische Race-Condition: 
Ist "MyThread" konstruiert bevor der Thread darauf zugreift oder nicht?
Das erklärt wahrscheinlich auch, warum es unter Windows (meistens, 
immer?) funktioniert: Hier scheint der Thread zum Loslaufen länger zu 
brauchen, als die Konstruktion von "MyThread".


Gruß,
Oliver

von Stefan (Gast)


Lesenswert?

Aber wenn ich den Thread innerhalb des Konstruktors der Klasse MyThread 
loslaufen lasse sollte alles ok sein, oder? Zu diesem Zeitpunkt müsste 
ja eigentlich die vtable schon fertig zusammengebaut sein...

von Oliver R. (superberti)


Lesenswert?

Nein, das Objekt muss erst vollständig konstruiert sein.

Also:

MyThread mythread;
mythread.Run();

Gruß,

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.