[ JustinTime @ 13.05.2008. 12:32 ] @
konkretno, imam niz integera koji su ustvari memorijske adrese dinamički alociranih objekata i/ili nizova. Eh, sad, znam da svakoj toj adresi mogu pristupiti konvertujući je u void*, ali ako baš hoću da znam o kojem se tipu podatka radi na datoj adresi...? Postoji li način?
[ X Files @ 13.05.2008. 12:45 ] @
Pogledaj dynamic_cast a takodje i static_cast, reinterpret_cast, i sl...

Pretrazi (search) i ovde po forumu, ima dosta primera...
[ JustinTime @ 13.05.2008. 13:00 ] @
Ma jasni su meni castovi svi odreda, možda se nisam dobro izrazio...

Znači, jasno je meni da će dynamic_cast da vrati null ako nije pogodio kojmpatibilan tip, ali ja u kodu imam previše tipova podataka da bih išao pokušaj-pogreška... Sve što imam je niz void pointera i sticajem okolnosti ne mogu da znam ni otprilike kojeg su tipa bili. znači ne znam je li char* ili je cSNMPInterface*. Imam samo adresu. znači, da li je moguće da saznam da li je na toj adresi char* ili cSNMPInterface* bez da radim:

Code:

char* p = dynamic_cast<char*>pMojVoidPointerIzNiza;
cSNMPInterface* p1 = dynamic_cast<cSNMPInterface*>pMojVoidPointerIzNiza;

if(p) onda ti je char*
if(p1) onda ti je cSNMPInterface*


Znači, napominjem, ova dva tipa sam naveo samo ilustracije radi, u stvarnosti ih imam na hiljade mogućih...
[ deerbeer @ 13.05.2008. 13:32 ] @
Citat:

znači, da li je moguće da saznam da li je na toj adresi char* ili cSNMPInterface* bez da radim:
Code:

char* p = dynamic_cast<char*>pMojVoidPointerIzNiza;
cSNMPInterface* p1 = dynamic_cast<cSNMPInterface*>pMojVoidPointerIzNiza;

if(p) onda ti je char*
if(p1) onda ti je cSNMPInterface*




A kako bi ti to voleo da to uradis ? Daj mi samo primer pa makar i najbanalniji ...
U toku runtime-a moras znati tip objekta koji cast-ujes tj. njegov "runtime-size" da bi mogao da konvertujes void* pointer u njegov class pointer ..
To sto imas hiljadu void* pointera u tvom nizu je problem tvog programa tj. implementacije jer ces morati da postavljas hiljadu if uslova .

Jedini izuzetak je kod nizova sa polimorfnim tipovima :
npr
Code:

 class CBase ; 
 class CcSNMPInterface : public CBase ; 
 class CNekaKlasa : public CBase ;  

 CBase*  nizBaznihObjekata [10] ; 


Al ces u tom slucaju moci da koristis samo funkcije i promenljive CBase klase
i takodje override-ovane funkcije iz nasledjenih klasa....


[Ovu poruku je menjao deerbeer dana 14.05.2008. u 09:56 GMT+1]
[ JustinTime @ 13.05.2008. 13:53 ] @
hm, pa nije to toliko pitanje toga kako bih ja to volio uraditi, nego kako mogu. nemam ja 1000 pointera u nizu, nego imam 1000 class tipova, a jednako je moguće da je bilo koji void* iz pomenutog niza ustvari bilo koji od tih 100 class tipova.

Da pobliže objasnim, niz koji sadrži void* se puni u overloadanom new operatoru:

Code:

void* operator new(size_t _Count)
{
    void* pRet = CMemObserver::GetInstance()->Allocate( _Count);
    return pRet;
}


void* CMemObserver::Allocate( size_t Bytes) 
{
    void* pPtr = malloc( Bytes);
        ...

    m_aiAllocated[sm_iAllocationIndex] = (int)pPtr;
        ...

    return pPtr;
}


Dakle, mogao bih još negdje i da spasim veličinu alokacije, ako bi bilo od pomoći, ali ne i tip pointera (bar ja ne znam kako, a volio bih da mi neko kaže ako zna). Kasnije kada budem vadio pointere iz m_aiAllocated, neću znati kojeg su tipa. Sve što pitam je, zna li neko, da li postoji nešto, neki operator ili tako nešto koji kaže:

Code:
kojeg_si_tipa_bio_kad_si_prvobitno_alociran( (void*)m_aiAllocated[neki_broj] )


samo to pitam.
[ deerbeer @ 13.05.2008. 14:13 ] @
Citat:
@JustinTime
m_aiAllocated[sm_iAllocationIndex] = (int)pPtr;

Ne mozes ...
Ako si ovde cast-ovao tvoj void* u int isto to moras i uraditi kad hoces da proveris tip na datom elementu niza (box-ing i unbox-ing pointera).

Citat:

Sve što pitam je, zna li neko, da li postoji nešto, neki operator ili tako nešto koji kaže:
Code:

kojeg_si_tipa_bio_kad_si_prvobitno_alociran( (void*)m_aiAllocated[neki_broj] ) ; 


Odgovor ti je dao XFiles na pocetku ..
[ bubasvaba79 @ 13.05.2008. 14:35 ] @
slazem se sa deerbeer-om!
[ JustinTime @ 13.05.2008. 14:41 ] @
Citat:
Ne mozes ...
Ako si ovde cast-ovao tvoj void* u int isto to moras i uraditi kad hoces da proveris tip na datom elementu niza (box-ing i unbox-ing pointera).


ne razumijem, šta ne mogu? Ovdje ti kažem šta radim. Da, castam void* u int, a šta tačno misliš da treba da uradim kad hoću da provjerim tip?

Citat:
Odgovor ti je dao XFiles na pocetku ..


Da sam pitao kako da castam void* u određen tip, to bi bio pravi odgovor! Međutim, ja pitam kako da znam koji je to određen tip, a da ne bude metodom pokušaja i pogrešaka.
[ bubasvaba79 @ 13.05.2008. 14:49 ] @
...onda najbolje da odustanes...
[ JustinTime @ 13.05.2008. 14:50 ] @
...ok, hajd recimo da je nemoguće (ako ne računamo dynamic_cast)... je li moguće znati o kom se tipu radi unutar overloadanog new operatora?

dakle

Code:

cKlasa *pKlasa = new cKlasa()


...pozvaće se operator new iz gornjeg primjera, je li moguće u njemu već znati konkretan tip, a ne samo veličinu?
[ JustinTime @ 13.05.2008. 14:52 ] @
Citat:
...onda najbolje da odustanes...

da, probaću i to, tebi hvala za doprinos...

[Ovu poruku je menjao JustinTime dana 13.05.2008. u 16:13 GMT+1]
[ Xarios @ 20.05.2008. 09:45 ] @
Citat:

...ok, hajd recimo da je nemoguće (ako ne računamo dynamic_cast)... je li moguće znati o kom se tipu radi unutar overloadanog new operatora?

dakle

Code:

cKlasa *pKlasa = new cKlasa()


...pozvaće se operator new iz gornjeg primjera, je li moguće u njemu već znati konkretan tip, a ne samo veličinu?


iz ovog gore KODA, konkretan tip je: korisnicki definiran tip, a to je 'cKlasa' ! On vraća pokazivač koji pokazuje na memorijsku adresu alociranu na gomili.
Pa zato imamo tipove podataka: standardne koji su uključeni u C++ (to vjerujem i ti znaš) i korisnički definirane tipove.

Ako želiš da ti program bude toliko pametan da alocira odredjenu memoriju na gomili koja je odredjenog tipa (podatka) u vrijeme izvršavanja (Run Time) u zavisnosti od nekog uvijeta (npr. hoce da mozda alocira int, long, ili korisDefTip() na gomili ovisno o trenutnom uvijetu koji je zadao klijentski program ili korisnik) onda koristiš: pokazivače na funkcije ili nizove pokazivača na funkcije.

A evo jedne informacije koja nije pouzdana jer se baš dobro ne sjećam ali mozda budeš provjerio negdje: ako nije definiran određen tip, onda je int (mislim prvenstveno kad se alocira memorija na gomili (heap)).

Vjerujem da ti nisam baš pomogao ali eto bar pokušao :)
[ kiklop74 @ 20.05.2008. 14:32 ] @
To sto ti hoces nije moguce uraditi u C++. Ne postoji nikakav standardan nacin za odredjivanje tipa podatka za koji se poseduje memorijska adresa i tacka.

Svi koji su spomenuli dynamic_cast nisu u pravu jer dynamic_cast ne podrzava kastovanje void*. Za te potrebe se koristi reinterpret_cast ali programer MORA da zna koji je tip podatka u pitanju jer je reinterpet_cast ekvivalentan C kastu tj. sve je u rukama programera i kompajler se tu ne mesa.

Evo i jednog malog primera koji demonstrira kako se lako gubi tip podatka:

Code:
#include <iostream>
#include <memory>
#include <typeinfo>

struct type1{
    type1() {}
    ~type1() {}
};

void typetest() {
    std::auto_ptr<type1> p(new type1);
    type1 *pptr = p.get();    
    void *unknown = static_cast<void*>(pptr);

    std::cout << "Tip pointera pptr je: "  << typeid(pptr).name() << std::endl;
    std::cout << "Tip pointera unknown je: " << typeid(unknown).name() << std::endl;

}


edit: sitne greske

[Ovu poruku je menjao kiklop74 dana 20.05.2008. u 20:44 GMT+1]

[Ovu poruku je menjao kiklop74 dana 20.05.2008. u 20:45 GMT+1]
[ JustinTime @ 20.05.2008. 14:47 ] @
Znači, Darko, ovo je TAČNO ono o čemu govorim. Hvala na odgovoru!

Pozz
[ StefanJer91 @ 20.05.2008. 16:19 ] @
A sto ne napravis jos jedan array, koji u stvari sadrzi informacije sta se na nekom mestu nalazi u array-u sa pointerima. Pretpostavljam da u array sa pointerima kada ubacujes pointer kazes znas i sta je to na sta taj pointer pokazuje. Drugi nacin koji je sredjeniji je da napravis strukturu koja sadrzi pointer i neku int promenljivu koja ce ti pomoci da znas koji je objekat u pitanju. Npr 0 je Klasa1, 1 je Klasa2 itd... Posle napravis array sa tim strukturama i to je to.
[ deerbeer @ 20.05.2008. 17:54 ] @
Citat:
@kiklop
.....ali programer MORA da znam koji je tip podatka u pitanju jer je reinterpet_cast ekvivalentan C kastu tj. sve je u rukama programera

E upravo je to ono sto JustinTime-u nisam uspeo da objasnim ....
Programer MORA da zna koji je tip podataka u pitanju a koji ce cast koristiti zavisi od implementacije
Sve u svemu mnogo price i polemike oko elementarnih stvari ...
[ gosha @ 20.05.2008. 19:19 ] @
RTTI

Poz. Gosha
[ kiklop74 @ 20.05.2008. 19:45 ] @
Citat:
gosha: RTTI

Poz. Gosha


Upravo smo apsolvirali da u navedenom slucaju RTTI ne pomaze.
[ gosha @ 20.05.2008. 23:42 ] @
Ma da se nesto skarabudziti :)

Code:

#include <iostream>
#include <memory>
#include <typeinfo>

struct type1 {
    type1() {}
    virtual ~type1() {}
    virtual void neka_vir_f() {}
};

struct type2 {
    type2() {}
    virtual ~type2() {}
    virtual void neka_vir_f() {}

};

int main() {
    std::auto_ptr<type2> p(new type2);
    type2 *pptr = p.get();
    void *unknown = static_cast<void*>(pptr);

    std::cout << "Tip pointera pptr je: "  << typeid(*pptr).name() << std::endl;
    std::cout << "Tip pointera unknown je: " << typeid(*(static_cast<type1*>(unknown))).name() << std::endl;

    std::system("pause");

    return 0;
}
[ kiklop74 @ 22.05.2008. 14:33 ] @
Interesantno ali ovo radi samo za klase koja imaju virtualne destruktore (vtable). Originalno pitanje je bilo:

Citat:
znači, da li je moguće da saznam da li je na toj adresi char* ili cSNMPInterface* bez da radim:


Code:

struct type1{
    type1() {}
    virtual ~type1() {}

};

struct type2{
    type2() {}
    virtual ~type2() {}
};

struct type3{
    type3() {}
    ~type3() {}
};

bool isObjectPtr(void *ptr) {
    bool result = (NULL != ptr);
    if (result) {
        try {
            const std::type_info& t = (typeid(*static_cast<type1*>(ptr)));
            std::clog << "Tip objekta na koji pokazuje pointer je: " << t.name() << std::endl;
        } catch (std::__non_rtti_object& nr) {
            std::cerr << "Pointer ne pokazuje na Objekat: " << nr.what() << std::endl;
            result = false;
        }        
    }
    return result;
}

void testptr(void *ptr) {
    if (isObjectPtr(ptr)) {
        std::cout << "Pointer pokazuje na Objekat" << std::endl;
    }
}

void typetest() {
    std::auto_ptr<type2> p(new type2);
    std::auto_ptr<type3> p2(new type3);
    char *test = new char[10];
    void *unknown = static_cast<void*>(p.get());
    void *unknown2 = static_cast<void*>(p2.get());
    void *chunk = static_cast<void*>(test);
    (unknown), (chunk);
    testptr(unknown);
    testptr(unknown2);
    testptr(chunk);
    delete [] test;

}

int _tmain(int argc, _TCHAR* argv[]) {
    (argc), (argv);

    typetest();
    return EXIT_SUCCESS;
}


Ovaj kod vraca sledece ( Visual studio 2008 ) :
Citat:

Tip objekta na koji pokazuje pointer je: struct type2
Pointer pokazuje na Objekat
Pointer ne pokazuje na Objekat: Access violation - no RTTI data!
Pointer ne pokazuje na Objekat: Access violation - no RTTI data!


Sto znaci da je upotrebljivost ovog trika veoma ogranicena jer ne detektuje klase koje nemaju vtable i ne detektuje eksplicitno tip native pointera.
Ako u jednacinu udje i int* osim char* korisnik je ponovo na pocetku. I dalje vazi zaklljucak da garantovanog nacina za 100%detektovanje tipa iz pointera nema ako se radi o opstem slucaju gde pointer moze da pokazuje na bilo sta.


[ gosha @ 22.05.2008. 16:03 ] @
Slazem se ja da u njegovom slucaju RTTI ne pomaze, ali isto tako kazem da je za tu problematiku najbolje koristiti RTTI.
Da bi ga koristio mora ipak da savlada sta je RTTI i sta mora da obezbedi u programu da bi to radilo.

Program ima koncepcijsku gresku koja je posledica ne poznavanja RTTI-ja.

Poz. Gosha
[ JustinTime @ 22.05.2008. 16:56 ] @
"Program" se zove trunk gateway i ima razbacan je u oko 400 .cpp fajlova. Nema koncepcijski problem proizašao iz nepoznavanja RTTI-ja nego problem sa curenjem memorije, te stoga pokušavam da kroz overload new i delete operatora, te malloc, calloc i realloc funkcija na neki način utvrdim kojeg je tipa pointer koji pokazuje na izgubljeni blok memorije.

Jedina koncepcijska greška ovdje je što prije nego si poletio da postaš link na Wikipediju nisi pažljivo pročitao o čemu se uopšte radi.
[ kiklop74 @ 22.05.2008. 20:20 ] @
Citat:
JustinTime: "Program" se zove trunk gateway i ima razbacan je u oko 400 .cpp fajlova. Nema koncepcijski problem proizašao iz nepoznavanja RTTI-ja nego problem sa curenjem memorije, te stoga pokušavam da kroz overload new i delete operatora, te malloc, calloc i realloc funkcija na neki način utvrdim kojeg je tipa pointer koji pokazuje na izgubljeni blok memorije.


Pa sto ne kazes da je to problem?!

Prvo reci koji kompajler koristis da bih ti rekao koji alat da koristis za detekciju curenja memorije.
[ JustinTime @ 22.05.2008. 23:33 ] @
eh, što kažu dok zec objasni da nije vo... :)

koristim vc++ 6.0 Ali to nije ni po muke. Našao sam bezbroj alata za detekciju leakova, ali problem je u tome što je riječ o embedded sistemu koji se vrti na Pharlapu. Tako da sam prisiljen da ga lovim ovako "ručno". Postoji i windows verzija aplikacije, ali na žalost na njoj ne mogu da simuliram leak.
[ NastyBoy @ 22.05.2008. 23:43 ] @
Htedoh da ti predlozhim templejtovani global new operator, ali kako je rech o embedded sistemu bolje je da se vratish na stari __FILE__ / __LINE__ postupak pracenja alokacija.
[ kiklop74 @ 23.05.2008. 03:06 ] @
To definitivno jeste problem. Dok ne budem imao malo vise vremena da pogledam sta ima na mrezi pokusaj sa ovim paketom za detekciju leakova. Podrzava gomilu operativnih sistema (pharlap nije na listi ali bi verovatno lako proradio i tamo):

Mpatrol
http://www.cbmamiga.demon.co.uk/mpatrol/
[ JustinTime @ 23.05.2008. 07:38 ] @
nasty: da, tome sam se i vratio. to je u krajnjoj konzekvenci ukinulo potrebu da znam tip podatka (samo odem u file i liniju i vidim :) ), ali problem sa curenjem ostaje, tako da ako imaš kakvu ideju... :)

kiklop: OK, probaću, hvala puno.
[ deerbeer @ 23.05.2008. 11:12 ] @
Citat:
.....ali problem sa curenjem ostaje, tako da ako imaš kakvu ideju... :)

Jedan savet za ubuduce posto ne verujem da mozes da prodjes kroz svih 400 *.cpp file-ova
Kad budes alocirao memoriju sa new operatorom , probaj sa DEBUG_NEW makro-om
(ne znam da li ga ima u VS6.0 al u VS2005 ga ima sigurno)..
Ako ga nema instaliraj neki sveziji SDK pogledaj na msdn-u.

A on upravo radi ono sto ti je @NastyBoy rekao
Obavezno radi pod "DEBUG" build-om
Code:
 
CKlasa klasa = DEBUG_NEW CKlasa() ; 

Kad izadjes iz debug-a tj. iz programa u Output prozoru ce ti se ispisati svi memory-leak-ovi u programu i njihove pozicije ..
Znaci : Memory leak detection : File *.cpp Line : 23 itd...
[ JustinTime @ 23.05.2008. 11:53 ] @
ma lako bih ja za 400 .cpp fajlova, jedan
Code:
#define new DEBUG_NEW
bi to riješio, ali mislim da je to podržano tek od 2003-ke :(
[ deerbeer @ 23.05.2008. 12:22 ] @
Mozes da prodjes kroz svih 400 fajlova i da uradis Search & Replace (new - > DEBUG_NEW) ;
Ako nisi instalirao neki svezi SDK na VS6.0 probaj sledece :
Code:

#define DEBUG_NEW new(THIS_FILE,__LINE__)

I onda uradi ono prvo sto sam ti naveo

[ NastyBoy @ 23.05.2008. 13:11 ] @
Ipak bih ti preporuchio da napravish svoj custom memory manager/tracker kao "drop-in replacement" i kroz njega pratish alokacije.
Imash dosta primera na tu temu, jedan (relativno mator) kog se mogu setiti u trenutku je: http://www.flipcode.com/archiv...senting_A_Memory_Manager.shtml (ako uopshte uspesh da dohvatish taj fajl)
[ deerbeer @ 23.05.2008. 13:43 ] @
Pa zavisi dosta koliko memory leak -ova ima u programu
i da li uopste zeli napredniji memory -management za svoj program ( da bi mogao da ga optimizuje )
zbog toga bi mozda bilo bolje da koristi neku custom bibilioteku.

Jer koriscenje DEBUG_NEW nije prakticno ako se nalazi u nekom *.cpp fajlu tj. klasi koju koristi jos nekih 100 drugih klasa-*.cpp u kodu
Output Debug prozor ce pokazivati gde je nastalo curenje memorije ...
al nece prikazivati odakle je pozvana funkcija u kojoj se alocirala nova memorija
(u tvom slucaju sa 400 fajlova ce ti se to verovatno desiti ako nisi dosad izolovao fajlove koji prave curenje memorije )

---------- dodato -----------
gornji link ne radi download .
evo nadjoh jedan na : http://www.codeproject.com/KB/applications/leakfinder.aspx




[Ovu poruku je menjao deerbeer dana 23.05.2008. u 20:00 GMT+1]