CreateThread of non-staticle or virtual Memberfunctions,...
-
IMHO Nein.
1. Zeiger auf Member Functions können so nicht verwendet werden...
2. Funktioniert nicht für 64bit.
3. Wie soll der this pointer hier gesetzt werden? Ist für mich nicht ersichtlich.Bau lieber eine statische Starter-Funktion, die eine Struktur übergeben bekommt, mit Zeiger auf Klasse, inkl. Zeiger auf die Memeber Funktion. Die dispatached dann.
BTW: All dieses rumkoperen, hättest Du auch einfacher über cast erreichen können.
-
Jo Martin,
danke für Dein Feedback,
-
Jo is richtig, für x64 kann man für die richtige addressbreite halt DWORD64 nehmen,...
-
Die zeile hatte ich eigentlich rauskopiert (weiß nicht warum),..
nach initthread wird lparam von ecx geladen und die vftbl erwartet für den call den this ptr auch auf ecx ,...
sr=(LPVOID)this; triTemp.hThread=CreateThread(NULL,dwStackSize,(LPTHREAD_START_ROUTINE)srt,sr,NULL,&dwTh);Somit wird der this ptr instanziell übergeben,...
zu 1) also der verwendung der MFP (Member function Pointers) muss ich zu http://www.codeproject.com/kb/cpp/FastDelegate.aspx referenzieren.
Für die verwendung von dem VS2008 Compiler scheint das doch konform zu sein,.. (?????)BTW) ja,... bei mir hat beim casten der compiler gemeckert,.. oder ich habe mich zu glatt angestellt,...
Du meinst:
static DWORD WINAPI _thread::_starter_func(LPVOID lpParam) { if(lpParam) return ((_thread::_thread_handler*)lpParam)->run(...); return 0; };??
Grüße und dank für weitere statements,....
-
-
Wenn Du den Cast nach LPTHREAD_START_ROUTINE brauchst, hast Du was falsch gemacht. Es muss ohne gehen. Cast ist hier keine Lösung, sondern nur ein Compiler Still-Macher.
-
... virtuelle memberfunktionen haben ne andere signatur als freistehende funktionen des typs DWORD( WINAPI*)(LPVOID) ...
Daher ist ein cast erforderlich und es ist somit klar das der compiler meckert,...
Relevant ist nur das ich ein fktptr für den start brauche, der ja offensichtlich für alle memberfkts exisitiert....Sinn der Übung ist es aber gerade threads (aus) einer non-staticle oder virtuelle memberfkt's zu erzeugen,...
Grüße
-
Und wer braucht das? Man kann es auch machen ohne auf Hacks zurückzugreifen.
Wie es geht habe ich beschrieben...Dir ist klar, dass der this Zeiger nicht bedeutet, dass die vtable, die Du für die Funktion benötigst an dieser Stelle liegt?
Die ist klar, dass ein Funktion-Member Zeiger eine Struktur ist, die aus einem this Zeiger plus einem Offset besteht?Nochmal: Um es für den Compiler richtig zu machen und nicht alles durch casts plattbügeln zu lassen würde ich lieber zu einer kontrollierten Übergabe neigen.
-
Martin Richter schrieb:
Und wer braucht das? Man kann es auch machen ohne auf Hacks zurückzugreifen.
Ja, im allgemeinen wird das evtl. nicht benötigt. Da sich ja aber die Addy, trotz fester Basisaddresse, der vtbl zu jeder Laufzeit ändert, würde dies einen "hackschutz" bedeuten.
Der hauptgrund jetzt ist aber wohl eher um noch etwas zu lernen, daher bitte ich um ein bisschen geduld mit mir.

Wie es geht habe ich beschrieben...
jup,..siehe oben,... danke
Dir ist klar, dass der this Zeiger nicht bedeutet, dass die vtable, die Du für die Funktion benötigst an dieser Stelle liegt?
Ich verstehe jetzt nicht ganz was Du meinst.
Die addy des vftbl eintrages für die aufzurufende memberfkt bekomme ich durchRun my_ptr=&_thread::_thread_handler::run;Der this ptr ist hingegen nur ein ptr zum datensegment der Instanz.
(bitte um korrektur wenn ich mich hier irre...)Die ist klar, dass ein Funktion-Member Zeiger eine Struktur ist, die aus einem this Zeiger plus einem Offset besteht?
Da bitte ich nochmal um klärung, da ich nicht ganz verstehe was Du hier meinst.

Denn prinzipiell ist ein fktptr sowie ein MFP (member function pointer) nichts weiter als ein offset (der unteranderem nach dem aufruf auf dem callstack abgelegt wird...) .Der this ptr (bei MFP's) sowie die parameter werden je nach callconvention in register (this ptr bei __stdcall in ecx)in dementsprechender reihenfolge abgelegt.
Daher verstehe ich nicht das du meinst mit this+0hXX = offset der member function ?????Grüße und dank

-
Was ist eine addy?

-
Entschuldige:
Addy = addresse , hier ist damit ein offset gemeint. Im speziellen der Offset der Vtable.Greetz

-
Schau Dir mal einen MFKT Ptr im Speicher an. Er hat bei der MS Implementierung für 32bit eine Größe von 64bit...
Eine gute Beschreibung dazu hat Raymond Cheang geschrieben, ob in seinem Blog oder seinem Buch weiß ich aktuell nicht mehr.
-
Hi Martin,
jetzt weiß ich was Du mit der Struktur meinst.
Wenn eine Klasse aus zwei Basisklassen besteht:
(folgend als multibles derivat bezeichnet)
||===== ||
|| base 1 ||
||===== ||
|| base 2 ||
||===== ||
| derived |
|====== |dann muss um eine methode aus der basis2 klasse aufgerufen werden der this ptr
adjustiert werden. D.h. der pointer zu der member funktion ist eine "reale"
struktur, bestehend aus dem eigentlichen offset der member funktion (pointer)
plus der größe einer size_t, dem Adjustor, welchen den this ptr auf das
Datensegment der zwoten basisklasse "konvertiert"
(im endeffekt ne offset addition).Bei einer Vererbung aus nur einer Basisklasse hingegen, ist der pointer auf
einen member der Basisklasse, nur so groß wie ein pointer.
(Auf 32bit systemen halt 4 byte)"The size of a pointer-to-member-function can change depending on the class!"
Ferner sollte man keine MFP eines multiblen derivats in eine MFP der basis casten, da sich sonst die größe des pointers ändert.
Quellen:
http://www.agner.org/optimize/calling_conventions.pdf
http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx
(Von Chen hatte ich jetzt direkt nix gefunden,.. ausser der historie von callin' conventions..)
-------------------------------------------------------------------------------Da der Adjustor vor dem Aufruf der Basismethode greift, wird dann der pure (offsetkorregierte) this ptr übergeben. Die Frage die sich jetzt an diesem Punkt stellt ist:
Wie sieht der this ptr einer virtuellen basis methode bei einem multiblen derivat aus, wenn dies einen eintrag in der vtable erzeugt ????
Das werde ich mir heute auf jedenfall noch anschauen

Grüüße und Dank,..
..anregungen sind willkommen
-
Hi,
also ich habe mal auf die schnelle etwas gebastelt:class Base1 { public: virtual void bm1(void) {}; }; class Base2 { public: virtual void bm2(void){}; }; class derived:Base1,Base2 { public: void bm2(void){}; };Und hier die dissambly, ich hoffe ich habe diese richtig übersetzt
Base2 * dptr= new Base2; // addresse: 0x013a6ee8 dptr->bm2(); // hole die addy des dptr ptrs 012510D2 mov eax,dword ptr [ebp-34h] // sichere die addy der vtable nach edx 012510D5 mov edx,dword ptr [eax] // sichere this pointer im ecx 012510D7 mov ecx,dword ptr [ebp-34h] // hole die addy der methode aus der vtable und sichere es in eax 012510DA mov eax,dword ptr [edx] // aufruf der methode 012510DC call eax derived * dptr2 = new derived; dptr2->bm2(); //hole die addy des pointers 0125111D mov ecx,dword ptr [ebp-38h] //adjustiere +4 byte für den call (this konvertierung) 01251120 add ecx,4 //hole pointer der instanz 01251123 mov eax,dword ptr [ebp-38h] // Hole die addy der vtable 01251126 mov edx,dword ptr [eax+4] //hole den offset der member func aus der vtable (von Base2) 01251129 mov eax,dword ptr [edx] //und call 0125112B call eaxFür mich heißt das, egal ob ich die virtuellen _thread::_thread_handler::_start
in einem multiblen derivat nicht überlade und dafür aber ::run , müsste ich also
den this ptr den ich übergebe NICHT anpassen.Ich kann halt zwar auf die vererbten elemente der basis1 nicht zugreifen aber
immer noch auf die der basis2 und die im derivat deklarierten, da sie im
speicherbereich nach dem ende von dem der basis2 liegen.Da aber so eine polydeklaration ja so oder so nicht erlaubt ist:
Base2 _ptr= new derived; //error C2243brauche ich mir um solch einen fall auch ja keinen kopf machen,...
Falls ich aber umgekehrt die ::_start überlade, und die ::run nicht, muss ich also
darauf achten das der this ptr adjustiert wird.Die oft genutzte polmorphe konvertierung üder die von Martin vorgeschlagene
externe (statische) ThreadProc funktion (siehe erste seite) würde aber aufgrund von C2243
Fehlschlagen, wenn es sich um ein multibles derivat handelt, ausser der this
pointer wird vorher adjustiert oder nicht???D.h. Ich müsste so oder so den this pointer vor der übergabe
adjustieren, egal ob es sich um eine externe ThreadProc oder eine interne
vrituelle meberfunc handelt, auch wenn es allein des datensegment geht.dringendes RFC (Request for Comments
)Grüße und dank...
-
Hier steht auch noch einiges über (Member-)Function-Pointer.
-
..danke asd,
darauf habe ich aber schon in der ersten seite des Threads referenziert

-
Oh sorry! Ich hatte mir den Thread durchgelesen, den Link aber anscheinend übersehen. Naja, hab ich ihn halt bestätigt oder so
