Newsgroup: it.comp.programmare.win32
Titolo: Oggetti dinamici/statici

Ciao,
vorrei sapere se esiste un sistema per capire (dal puntatore dell'oggetto)
se l'oggetto è stato dichiarato in modo statico
CNomeClasse NomeOggetto;
oppure in modo dinamico
CNomeClasse *NomeOggetto;
NomeOggetto = new CNomeClasse();
Le classi possono essere derivate dalla CObject se necessario.
In alternativa esiste un modo per forzare l'utente (sto facendo una libreria
da distribuire) a dichiarare gli oggetti in modo dinamico altrimenti far
dare direttamente dal compilatore un errore? Mi sembra che una volta mi ero
imbattuto in una classe di questo tipo...
Ciao e 1000 grazie a tutti
--
per rispondere togliere NEW
Gaggioso il portale della pesca 
http://www.gaggioso.it

 Le classi possono essere derivate dalla CObject se necessario.
Compila questo codice e trae le tue conclusioni:
#include <windows.h>
#include <stdio.h>
int ok[5];
int ok2[5] = {1, 2, 3, 4, 5};
int *ok3;
void main()
{
 int ok4[5];
 int ok5[5] = {1, 2, 3, 4, 5};
 int *ok6;
 ok3 = new int[5];
 ok6 = new int[5];
 printf("%08x\n", ok);
 printf("%08x\n", ok2);
 printf("%08x\n", ok3);
 printf("%08x\n", ok4);
 printf("%08x\n", ok5);
 printf("%08x\n", ok6);
}
Kiuhnm

mhh...... sei abbastanza enigmatico.....
questo il risultato
 ok=00427c6c
ok2=00424a30
ok3=002f07a8
ok4=0012ff6c
ok5=0012ff58
ok6=002f07f0
deduco che se faccio l'and logico con 00200000 e risulta 1 allora è allocato
dinamicamente altrimenti no!
Ho capito giusto? Siamo sicuri che tutti i puntatori faranno parte di quel
range (00200000-002FFFFF)?
Il tuo, è stato un colpo di genio o hai letto qualcosa da qualche parte?
Secondo me con tutti i possibili switch che ci sono nel compilatore per
modificare le dimensioni dello stack, ottimizzazioni dello stack..... ho
paura che non sempre funzioni questo metodo.... che ne dici?
1000 grazie.
Attendo comunque conferma.
Mauro
--
per rispondere togliere NEW dall'indirizzo
remove NEW from address to answer


 range (00200000-002FFFFF)?
In pratica funziona (con qualche aggiustamento), ma è poco portabile.
Perchè invece non provi a definire l'operatore new?
Kiuhnm

 dinamico
ma soprattutto, perchè? :-)
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!

Ok...il perchč gli hai fatto compilare il codice l'ho capito: gli hai fatto
vedere come č organizzata la memoria di un processo in presenza di variabili
globali, puntatori (che sono nello heap) e variabili locali (sullo stack).
Ma, ovviamente, l'indirizzo di partenza dello heap sarą di volta in volta
diverso...la new ritorna l'indirizzo di memoria...mi sfugge la
conclusione....   ;-)

 all'immagine in memoria di qualche DLL. Facile, no? :-)
What?
E dove lasci lo stack?
Kiuhnm

 memoria...mi sfugge la conclusione....   ;-)
All'inizio pensavo di procedere in questo modo:
main/WinMain()
{
    DWORD StackAddr;
    _asm mov    StackAddr, ebp
    .
    .
    .
}
EBP contiene l'indirizzo dello stack in questo stato:
PARAMN
.
.
PARAM2
PARAM1
EBP <------ EBP
cioè [EBP+4] = PARAM1, ecc...
Visto che main/WinMain è la prima funzione-utente a venire chiamata, EBP è
una buona approssimazione della cima dello stack.
Lo stack cresce verso il basso (verso indirizzi minori) quindi qualsiasi
indirizzo non compreso in [CUR_ESP, StackAddr] e maggiore del valore
ritornato da GetProcessHeap() apparterrà all'heap ==> allocato
dinamicamente.
Kiuhnm

 E dove lasci lo stack?
da quando si allocano oggetti dinamici nello stack ?
cmq penso anch'io che la soluzione di ridifinire l'operatore new si la
migliore
ciao

>ritornato da GetProcessHeap() apparterrà all'heap ==> allocato
Ignoravo l'esistenza di questa funzione...ovviamente sapendo l'indirizzo
dello heap si può fare una semplice verifica.

 all'immagine in memoria di qualche DLL. Facile, no?
What?
E dove lasci lo stack?
---------
void func()
{
    int r[5];
}
r è non-dinamico, quindi statico. Dove pensi che si trovi???
Dal discorso di mgaggia si capisce che per statico non intende globale o
globale con scope limitato (tipo static int var), ma una variabile non
allocata in modo dinamico con l'operatore new.
Kiuhnm


Però bisogna stare attenti!
il mio "memory layout" (Win98SE) è qualcosa del genere:
EXE MODULE: [401000, 404FFF]
GetProcessHeap() = 405000
Stack = [?, 500000]
FirstDinamicVar = [780000]
Come vedi bisogna prendere tutto l'heap escludendo lo stack (e le sezioni
del modulo in memoria).
Cmq. probabilmente lo stack occupa la prima parte dell'heap e quindi dopo
500000 (nel mio caso) dovrebbe esserci solo heap libero.
Kiuhnm

 allocata in modo dinamico con l'operatore new.
 verissimo sorry mio errore..
ciao :)))

 Cmq. probabilmente lo stack occupa la prima parte dell'heap
mi auguro di no. Un HeapFree() su una variabile automatica potrebbe 
avere risultati semplicemente disastrosi, se fosse cosě. Mi risulta che 
lo stack sia semplicemente un pezzo di memoria senza fronzoli (a parte 
un guard sulla pagina piů alta tra quelle non allocate) allocato con 
VirtualAlloc()


Kiuhnm ha scritto:

static non alloca sempre nel .data, scusa?


WOW che attivi....
Mi spiego meglio visto che ho creato un po di confusione...
Devo fare questa libreria con una decina di classi. Per il normale
funzionamento della libreria (che non sto a spiegarvi altrimenti sto qui
10gg) ci saranno probabilmente qualche centinaio di dichiarazioni di oggetti
in un semplice utilizzo, quindi pensavo senza far adoperare smart pointer o
simili, ogni volta che viene creato un oggetto volevo metterlo in un array e
quindi alla chiusura del progetto liberare/chiudere gli oggetti
eventualmente "dimenticati" per evitare memory leak che nel caso di
dichiarazione in DLL non vengono segnalati dal compilatore. Chiaramente se
l'oggetto viene dichiarato in modo statico (per me significa non con
operatore new) non deve essere liberato perchč si arrangia il sistema. Nel
costruttore e distruttore delle classi aggiungo o tolgo il puntatore dal
vettore di puntatori. Il tutto deve essere trasparente all'utilizzatore. Per
questo la scelta migliore per me sarebbe forzare la creazione con NEW.
Spero di essere stato piů chiaro.
Ciao e 1000 grazie a tutti
--
per rispondere togliere NEW dall'indirizzo
remove NEW from address to answer


 allocato con VirtualAlloc()
E come spieghi i valori che ho riportato?
Non li ho inventati...
Kiuhnm

 static non alloca sempre nel .data, scusa?
No:
static int a = 4;
si trova in .data (anche .idata, DATA)
static int b;
in .bss (anche BSS)
Comunque per mgaggia (forma un aquilone col vento che spira da SudEst)
statico significa non dinamico e quindi include lo stack.
Kiuhnm

 e 1000 grazie a tutti
Forzare la creazione con NEW non mi sembra troppo bello...un programmatore
può avere mille motivi per non voler usare new in certi casi.
E comunque hai due possibilità:
- nel costruttore ti "annoti" gli oggetti "statici" (i rimanenti saranno
dinamici)
- nell'operatore new e new[] ti "annoti" gli oggetti dinamici (i rimanenti
saranno "statici")
Ovviamente è preferibile il secondo :-)
Kiuhnm

 wrote in message
news:zTq69.209144$Jj7.4...@news1.tin.it...


 Non li ho inventati...
nemmeno io sto inventando quello che dico :-) non resta che fare la
prova:
#include <windows.h>
int main(void)
{
 int blah;
 HeapFree(GetProcessHeap(), 0, &blah);
 Sleep(0);
 return 0;
}
qui da me (Windows 2000) salta fuori questo messaggio:
HEAP[doh.exe]: Invalid Address specified to RtlFreeHeap( 130000, 12ff88 )
e non succede niente. Da te che fa?


 in .bss (anche BSS)
qual è la differenza?


 e non succede niente. Da te che fa?
Da me GetLastError ritorna ROR_INVALID_PARAMETER!
Kiuhnm

 qual è la differenza?
La sezione .data contiene dati inizializzati, mentre la .bss non
inizializzati e quindi la sezione .bss ha virtual_size > 0 e raw_size = 0!
(cioè non occupa spazio nel file PE).
Kiuhnm

 raw_size = 0! (cioè non occupa spazio nel file PE).
'razie. Sai anche dove trovare la descrizione delle altre sezioni? 
(beh, a parte .text. E .idata. E .edata. .rsrc. PAGE*. POOL*... ehm, 
quante ne rimangono? :-)
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.20. C, C++ and ASM developers


 Da me GetLastError ritorna ROR_INVALID_PARAMETER!
visto? non è nell'heap. Altrimenti già al ritorno da HeapFree avresti 
dovuto avere un'access violation
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.20. C, C++ and ASM developers


 quante ne rimangono? :-)
Non le conosco tutte...nessuno vieta di chiamarle *pippo* o *pluto*: quelli
che contano sono i flag!
Kiuhnm

 ok6=002f07f0    // heap
Anche da me la situazione non è differente, quindi c'è una sola spiegazione:
GetCurrentHeap() *non* ritorna l'indirizzo dell'heap del processo, ma
va_a_capire_che_cosa :-)
Kiuhnm

 *pluto*: quelli che contano sono i flag!
capito, ma mi pare di capire che ci siano delle convenzioni, no? (in 
kernel mode il nome conta, comunque. Un nome PAGE* significa che la 
sezione dev'essere paginabile, POOL* - suppongo - che debba risiedere 
in una pool)


 del processo, ma va_a_capire_che_cosa :-)
Appunto :-) Ritorna l'indirizzo della struttura RTL_HEAP che descrive 
l'heap :-))) E' tutto spiegato nel Pietrek


 l'heap :-))) E' tutto spiegato nel Pietrek
E allora che cosa volevi dimostrare con HeapFree? :-)
Kiuhnm

 in una pool)
Ti riferisci ai driver .sys, vero? Non li ho ancora studiati. Lo farņ quando
passerņ a WinXP; per ora uso soltanto i Vxd.
Kiuhnm

Kiuhnm ha scritto:

che lo stack non è allocato dallo heap :-)


 Non li ho ancora studiati.
non sono altro che delle DLL. Tutto un altro mondo rispetto a Windows 
98


 che lo stack non è allocato dallo heap :-)
Continuo a non capire. Se la HeapFree ritorna 0 e quindi *non* funziona, che
cosa dimostri?
L'heap principale potrebbe non essere deallocabile o essere stato allocato
in altro modo.
(hai detto che sarebbe dovuto saltare tutto!)
Kiuhnm

 (hai detto che sarebbe dovuto saltare tutto!)
eggià, perchè lo stack sarebbe stato liberato, quindi già al ritorno da 
VirtualFree/NtFreeVirtualMemory sarebbe dovuto saltare tutto. E in 
silenzio, perchè senza più stack non puoi nemmeno eseguire l'exception 
handler :-) (o forse la catena dell'exception handler usa uno stack a 
parte? dovrei controllare)


 parte? dovrei controllare)
In silenzio fino a un certo punto!
"L'applicazione ha eseguito un'operazione invalida" comparirà sempre e
comunque perchè ogni Ring ha il proprio stack (così i programmi in Ring 3
non possono fare saltare quelli in Ring 0).
Ring 0 -> Ring 0? Salta tutto....a meno che non vengano usati Task Gate
nell'IDT, ma la MS non pare apprezzarli (sono lenti).
Forse nel mio debugger li userò....sono ancora molto indeciso......
Kiuhnm

 Gate nell'IDT, ma la MS non pare apprezzarli (sono lenti).
di che si tratta? e a che servono, che non ho capito? :-)


 di che si tratta? e a che servono, che non ho capito? :-)
Servono per il multitasking.
TSS = Task State Segment
Ogni TSS contiene lo stato di un task (registri, stack-ring0, stack-ring1,
stack-ring2, io-table, cr3 (page table base address), ecc...).
Con CALL, JMP, IRET si può passare implicitamente da un TASK all'altro.
I TaskGate sono invece Int Gate (IDT) che puntano a TSS. In pratica ogni
volta che viene generato l'int, viene eseguito un Task Switch e per questo
motivo viene anche modificato ESP (perfino se non si cambia Ring).
Sono tentato di usare i TSS (ma complica tutto per una serie di
motivi.......principalmente perchè Windows *non* usa i TSS (o meglio ne
definisce uno che resta sempre quello corrente) e il debugger deve erigere
una barriera tra windows e i TSS) in modo da poter debuggare codice Ring 0
con stack invalido:
mov    ebp, esp
mov    esp, IDT_Address ;-)
mov    eax, ebx
mul    ecx
.
.
.
mov    esp, ebp
Debuggare questo codice è poco consigliabile con gli Int Gate!!!
Invece con i TaskGate non ci sono problemi.
Penso che aggiungerò i TaskGate come opzione per l'utente avanzato, ma solo
quando il debugger sarà perfettamente funzionante.
Ma prima devo aggiungere l'assemblatore e il decompilatore interattivo per C
(se ci riesco) :-)
Kiuhnm