Newsgroup: it.comp.lang.delphi
Titolo: puntatori, windows, memory management

Qualcuno mi sa dire brevemente perchè dichiarata la classe:
TProva = class
  public
    a : Integer;
    procedure seta(i : Integer);
end;
procedure TProva.seta(i : Integer);
begin
  a := i;
end;
eseguendo la seguente procedura:
procedure test;
var
  x : TProva;
begin
  x.seta(8);  // LINEA 1
  Button1.Caption := IntoStr(x.a); // LINEA 2
end;
Eseguendo sia la LINEA 1 e LINEA 2 NON viene generata un'eccezione (nè
su win98 nè su NT) pur essendo x non inizializzato (e quindi punta ad
un'area di memoria a caso)?
Grazie mille in anticipo,
  Marzio

 wrote in message
news:3DA3EE38...@mcee.it...

Controlla bene le opzioni e se veramente viene eseguito il codice (metti un
po' di breakpoint).
Ho provato il tuo codice e correttamente solleva un'eccezione alla chiamata
della procedura seta.
Stai usando per caso D7 con .net?

 Stai usando per caso D7 con .net?
Uso Delphi 4 update 2 e ovviamente ho provato ad inserire i breakpoint (infatti
non ci credevo neppure io).
Comunque sono sicuro che il codice viene eseguito in quanto con la LINEA 2
cambio correttamente la caption di un bottone della finestra ...
Qualcuno ha lumi?????

 un'area di memoria a caso)?
Perche' l'uso di memoria non inizializzata non implica necessariamente che
si sollevi un'eccezione.
--------------------------------
Inviato via 
http://usenet.libero.it

un'area di memoria a caso)?
Delphi5 dà un warning:
"Variable 'x' might not have been initialized"
Comunque la cosa strana è che funziona, quando teoricamente non
dovrebbe :)
-- 
A lurker.

 dovrebbe :)
Il concetto di "funzionamento", questo caso, e' in discussione.
Un programma corretto sicuramente funziona, un programma funzionante non
necessariamente e' corretto (a meno di intendersi con "funzionamento e'
funzionamento solo se il programma e' anche corretto").
Quando assegni un valore alla memoria puntata da un puntatore non
inizializzato, non e' affatto detto che si sollevi un'eccezione. Esempio, il
seguente codice e' sbagliato, nonostante funzioni:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
var
  P: ^Integer;
  A, B: Integer;
begin
  A := 3;
  B := 5;
  New(P);
  P^ := A;
  WriteLn(P^);
  Dispose(P);
  P^ := B;
  WriteLn(P^);
  ReadLn;
end.


inizializzato, non e' affatto detto che si sollevi un'eccezione.
A questo punto la domanda č: perchč?
Si tratta solo di fortuna - il puntatore non inizializzato puň puntare
a caso su zone di memoria valide/non valide - o cos'altro?
-- 
A lurker.

 A questo punto la domanda č: perchč?
Si tratta solo di fortuna. Passeggiare nella memoria inizializzata non
produce effetti evidenti sino a che non tocchi zone protette.


produce effetti evidenti sino a che non tocchi zone protette.
Piccola critica alla Borland:
A questo punto non sarebbe stato meglio che invece di un warning
delphi mostrasse un bell' error? 
In effetti non sembra tanto logico affidarsi alla fortuna.
Lasciare puntatori non inizializzati in giro per il codice non sembra
buona cosa, e non dovrebbe essere difficoltoso da diagnosticare da
parte del compilatore.
Boh.
/me dubbioso :)
-- 
A lurker.

 parte del compilatore.
Infatti non e' difficoltoso, e' impossibile.
Non e' il compilatore che decide di lasciare puntatori non inizializzati.
Vedi gli esempi nel thread passato per capire perche'.


 /me dubbioso :)
nessuno ha mai detto che la programmazione sia facile.
potresti provare a usare Java, da questo punto di vista e' un
linguaggio piu' "soft"...

Vedi gli esempi nel thread passato per capire perche'.
Appunto. Anche col codice che hai postato tu da un warning.
Stavo solo pensando se non fosse meglio dare un error al posto del
warning.
-- 
A lurker.

linguaggio piu' "soft"...
Non sostituirei Delphi con Java neanche sotto tortura ;)
-- 
A lurker.

 Appunto. Anche col codice che hai postato tu da un warning.
Ma dove ? ma quando ?


Anche col codice che hai postato tu da un warning.
Ops, avevo confuso il tuo esempio con quello di Marzio.
Col tuo esempio non dà nessun messaggio durante la compilazione,
eppure è presente un grave errore.
L'help di Delphi è molto chiaro a riguardo:
"After a call to Dispose(P), the value of P is undefined and it is an
error to reference P."
Eppure il compilatore fa finta di niente :-\
 
-- 
A lurker.

 Eppure il compilatore fa finta di niente :-\
Certo. L'help di Delphi dice una cosa molto diversa da quella che tu
intendi.
L'help afferma che e' un errore *logico* accedere alla memoria puntata da P,
ma non puo' e non deve impedire che tu lo faccia. Il puntatore, difatti,
potrebbe subire una dispose ed essere assegnato ad una zona di memoria gia'
allocata. In questo caso, anche se precedentemente ha subito una Dispose, il
suo "valore" e' valido.
Immagina la seguente situazione:
Puntatore
A -------------> [0x00001230]
B -------------> [0x00001234]
C -------------> [0x00001238]
Immagina che io compia una dispose su B:
Ora alloco il puntatore D:
A -------------> [0x00001230]
C -------------> [0x00001238]
D -------------> [0x00001234] (viene riciclata la memoria liberata)
Ora, se scrivo B := D, ottengo:
A -------------> [0x00001230]
B -------------> [0x00001234]
C -------------> [0x00001238]
D -------------> [0x00001234]
e B torna a puntare a della memoria valida.
B, nonostante precedentemente abbia subito una Dispose torna a puntare a
della memoria valida. Delphi dice che l'uso di B sarebbe indefinito, dopo la
Dispose, perche' tutto dipende se allochi D o meno (e anche in questo
secondo caso non e' detto che l'uso di B comporti degli access violation o
quant'altro).


quant'altro).
Ok. Grazie per avermi chiarito questo concetto _teorico_ :)
Meno male che _praticamente_ non c'č mai bisogno di fare un uso cosě
contorto dei puntatori, ... o sbaglio?
-- 
A lurker.

 contorto dei puntatori, ... o sbaglio?
Sbagli. I puntatori vengono usati quasi sempre a questo modo.


Sbagli. I puntatori vengono usati quasi sempre a questo modo.
Fammi capire meglio: tu dici che...
"...perche' tutto dipende se allochi D o meno (e anche in questo
secondo caso non e' detto che l'uso di B comporti degli access
violation o quant'altro)"
...e poi affermi che i puntatori vengono usati sempre in questo modo?
Cioč tu programmi affidandoti alla fortuna? Boh...
-- 
A lurker.

 Cioč tu programmi affidandoti alla fortuna? Boh...
Niente affatto, non hai compreso bene. Rileggi il thread e quello passato,
sull'argomento.
Il succo e' che quando si programma usando i puntatori non e' possibile
stabilire se la memoria puntata sia valida o meno. Non ci puo' fare nulla il
compilatore, non ci puo' fare nulla Borland.
