C++ constructor stack igénye? Lehet-e virtual fn egy constrálásban?
Egy objektum konstruálását adott llvm-gcc (xcc) fordító úgy teszi, mintha virtuális függvény lenne a constructor (vagy a hívási fában valahol).
Ennek van bármiféle teoretikus oka?
Szerintem sose virtual egy constructor, mert mindenhol a konstruálás során tudjuk hogy milyen tipusúak a memberek és ősök, amit konstruálni kell, és tudjuk azok pontos tipusát, ergo a constructorokat is.
Adott llvm-gcc compilert (xcc) használva ebben a környezetben minden függvényre kiszámítják a stack szükségletet, ezáltal biztosítva, hogy egy függvényt hívó kód elegendő stack-et allokáljon belépéskor. Ennek amúgy nem lenne sok értelme, de itt több szálú kód fordul, és több stack van, blabla.... Szóval a lényeg, hogy a compiler felcimkézi a függvényeket, hogy mennyi a max stack szükséglet.
Teoretikusan egy virtual fn esetében érthető (több gyerek esetén) hogy a tipus ismeretében se tudjuk hogy melyik virtual fn implementáció fog meghívódni futáskor, igy a max stack se tippelhető. Ez világos... Ennek az az alapja, hogy egy már létező objektumról nem tudjuk hogy miképpen lett konstruálva. Márpedig a virt fn meghívása azzal kezdődik, hogy feloldunk egy tipusos pointert, az az infó elvész, hogy a túloldalon a gyerekek közül melyiket tartalmazza futásidőben a vmt... (de egy constructor csak a tényleges allocator esetén hívodik meg, ami mindig tipusos) Destructor esetében tudjuk, hogy létezik virtual, de constructor esetében nem látom momentán semmi értelmét. :)
A jelenség az, hogy bárhol meghívhatok egy member függvényt, ha tudom a tipusát, csak virtual member fn-t nem, mert akkor a linker számára hiányzik a stack infó (meg kell adni kézzel). Nos, a helyzet úgy fest, hogy a constructorok esetén is hiányzik ez az infó a linkernek, hibát ad akkor, ha egy fn allokálni készül egy osztály példányt (ott constructor hívás lesz). (ha nem allokál, hanem obj ptr van akkor minden oké). Magyarra lefordítva a fordító virtuál fn-ként fordítja (nem ismeri a hivási fáját) a constructoroknak... Miért?
Egyszerű esetben is elhasal a linkelés, nagyon nem tudok másra gondolni, mint félbehagyták a c++ fordító ezen részét :). Mivel teoretikusan szerintem ismertnek kéne lenni egy osztály constructor fn hivási fájának minden esetben ami eszembe jut...
A fennti probléma/kérdés olyan esetre vonatkozik (sajnos), amikor sehol sincs vmt használat , semmi virtual nincs a kódban, és egy constructor blockban sincs fn hívás. (alap)





>> Szerintem sose virtual egy constructor, mert mindenhol a konstruálás során tudjuk hogy milyen tipusúak a memberek és ősök, amit konstruálni kell, és tudjuk azok pontos tipusát, ergo a constructorokat is.
A konstruktor sohasem virtuális. A virtuális függvény azt jelenti, hogy az objektumhoz tartalmaz egy pointer (a memóriában az elején) egy virtuális függvénytáblára ami az osztály sajátja és ebben vannak a virtuális függvényekre mutató pointerek. A konstruktor nem lehet ilyen.
Amiről te bészélhetsz, bár elég zavaros az a fordító számára átlátszatlan függvények esete. Amikor csak a deklarációt látja a header-ből, de nem látja a definíciót.
Küldjél példakódot, mert ezt én nem tudom produkálni gcc-vel.
Köszi a választ. A fordító és a linker között olyan nyilvántartás van, ami alapján mellékes hogy .h vagy .cpp fileban volt eredetileg (részben vagy teljesen) leírva a constructor. Ezért nem menteném fel a linkert a helyes eredménytől. :) Mire linkelésig jutunk, minden tipus ismert (kéne hogy legyen). Tehát a fennti esetben azt a hibaüzenetet adja a fordító, hogy egy ismert típusú fn-ről nem tudja a stack szükségletet eldönteni és nem azt, hogy nem ismer egy tipust. Ergo a constructorhoz nem készül el az nstack info...
Lehet olyan, hogy egy member ptr-t a constructor on-the-fly construál, szóval meghív egy másik osztály constructorát. Ebből fakadhat mondjuk rekurzió, ami már tényleg problémás...
Azért problémás a rekurzió, mert minden fn-t ismerünk, de nem ismerjük hányszor fogja meghivni önmagát... Mondjuk ez is elég vad (nem, nem volt rekurzió se a kódomban) :).
A szitu az, hogy van egy spéci cpu aminek a linkere részben rossz szerintem. De csak akkor, ha multithreades pontról hivnak (tehát az esetek egy részében) egy cpp függvényt, és csak akkor ha konstruálunk vagy virtuális fn-t hivunk. Az utóbbit értem, az elsőben nem látom a probléma okát. A linker működése komplikáltabb, ha többszálú pontra készít tárgykódot. A komplikált algoritmusai pedig felhasználják az nstack információt, ami a két említett esetben nincs. És a kérdésem arra irányult, hogy elméleti okból nincs-e :) Rekurziv, vagy virtual fn esetében értem hogy elméleti okból nincs. Constructor esetében nem látom hol van itt a rekurzió, vagy a virtual fn hívás lehetősége...
Irok egy kódot:
class A{public: int a; int fn1(){return a++;} };
//ez a fn miatt linker errort kapunk a constructorra
A* getSingleton(){
static A* p=new A(); //constructor hívás az első belépéskor fut le, mert static.
return p;
}
//ez no para
void wrapper1(){
A* pA= getSingleton(); //beszerezzuk az obj ptr-t.
int a= pA->fn1(); //itt tag fn-t hivunk.
}










Erre a static-os problémára nem gondoltam. :) Köszi, utána járok mit fordít arra. Ettől független a bajom.
Elméleti okát keresem annak, hogy a costructorok fája mikor nem bejárható. Ott tartunk, hogy ha kézzel beleírok egy virtual vagy egy rekurziv fn hívást a constructor kódjába, csak akkor nem. De alapból egy sima konstruálás mindig bejárható.
Rákérdezek a fejlesztőknél is, csak nem akartam valami bődületes baromsággal indítani :). Mert úgy fest valamit nem fejeztek be a fordító kódjában. :) Az is lehet hogy az egész constructor fa bejárás nincs befejeze (?) :) erre irok majd egy tesztet... De lényeg hogy valami nem jó...
A cucc egyébként egy olyan CPU-ra fordít amin hw-esen támogatott a szálkezelés és erőforrás allokáció. Szóval true párhuzamos futás van egyszerre sok magon. Ez kb azt jelenti, hogy egy cpu utasítás hatására el tud indulni n darab másik szabad magon ugyanez a kód (folytatása), úgy hogy mindegyik stack-et X-el eltolja.(Ahhol az X csak annyi, amennyi az adott ponton szükséges). Magyarán a fordító olyan kódot készít ami lehetővé teszi ezt, a cpu pedig kvázi úgy mint egy ugró utasításnál, natívan végrehajtja. Ez veszett gyors, a fordítónak meg az a feladata, hogy megadja a stack méretet minden fn-re, kivéve amire elméletileg lehetetlen megadni... Ez volt itt a question. :)
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!