camaleonteplus (Normal User)
Pro
Messaggi: 95
Iscritto: 05/03/2009
|
Nel chiedere il Form2 sulla X mi da questo errore:
"Access Violation"
il codice per aprire la Form2 è:
Codice sorgente - presumibilmente Delphi |
procedure TForm1.Button1Click(Sender: TObject); Var Form2 : TForm2; begin Form2 := TForm2.Create(TForm2); Form2.Show; end;
|
Come posso procedere? -Thanks
|
|
lorenzo (Normal User)
Guru
Messaggi: 1178
Iscritto: 15/04/2008
|
il problema secondo me è la variabile locale.
Quando il form2 si apre, la variabile Form2 viene allocata nello spazio di memoria della funzione Click come variabile locale.
Una volta terminata la funzione la variabile viene eliminata con la sua memoria e, quando il form2 viene chiuso, non trova più la memoria correttamente associata e tenta di pulire lo spazio appartenente a qualcun altro. Da qui il messaggio di errore.
Per risolvere o dichiari Form2 come globale(inteso come variabile membro di Form1 che è la classe principale del progetto) oppure la crei come finestra Modale: in quest'ultimo caso Form2 deve essere chiuso PRIMA di uscire dalla funzione click e quindi il problema della memoria non si pone.
|
|
a_butta (Member)
Expert
Messaggi: 578
Iscritto: 16/03/2010
|
Codice sorgente - presumibilmente Delphi |
procedure TForm1.Button1Click(Sender: TObject); Var Form2 : TForm2; begin Form2 := TForm2.Create(Application); Form2.Show; end;
|
Il problema non è la variabile locale! Hai creato un'altra form ma allocandola all'interno di se stessa!
|
|
lorenzo (Normal User)
Guru
Messaggi: 1178
Iscritto: 15/04/2008
|
Postato originariamente da a_butta:
Codice sorgente - presumibilmente Delphi |
procedure TForm1.Button1Click(Sender: TObject); Var Form2 : TForm2; begin Form2 := TForm2.Create(Application); Form2.Show; end;
|
Il problema non è la variabile locale! Hai creato un'altra form ma allocandola all'interno di se stessa! |
eh? che vuol dire? |
|
Goblin (Member)
Expert
Messaggi: 375
Iscritto: 02/02/2011
|
Postato originariamente da lorenzo:
Postato originariamente da a_butta:
Codice sorgente - presumibilmente Delphi |
procedure TForm1.Button1Click(Sender: TObject); Var Form2 : TForm2; begin Form2 := TForm2.Create(Application); Form2.Show; end;
|
Il problema non è la variabile locale! Hai creato un'altra form ma allocandola all'interno di se stessa! |
eh? che vuol dire? |
Guarda la leggera differenza nel codice che hai postato tu e il codice di a_butta, nel tuo codice metti come owner della classe TForm se stesso, e già questo errore non dovrebbe farti compilare in quanto la procedura create del TForm vuole un Tcomponent come owner e tu gli passi una class reference, invece a_butta mette come owner della della classe TForm l'applicazione stessa, in questo modo si para le chiappe da possibili memory leak nel caso in cui l'applicazione viene chiusa dal main, ma qui andiamo OT.
Riassumendo:
Se vuoi fare il semplice show di una form che hai creato visualmente, se non l'hai tolta dall'autocreate ti basta fare una uses e uno show, altrimenti la devi creare, ma la variabile l'hai gia includendo la form nelle uses.
G
Ibis redibis non morieris in bello |
|
camaleonteplus (Normal User)
Pro
Messaggi: 95
Iscritto: 05/03/2009
|
Continua a dare lo steso errore di memoria.
|
|
lorenzo (Normal User)
Guru
Messaggi: 1178
Iscritto: 15/04/2008
|
ma hai fatto quello che ti ho suggerito?
|
|
Goblin (Member)
Expert
Messaggi: 375
Iscritto: 02/02/2011
|
Postato originariamente da camaleonteplus:
Continua a dare lo steso errore di memoria. |
Qualche informazione aggiuntiva, per esempio cosa fai in form2?
il semplice codice :
var Form2: TForm2;
begin
Form2 := TForm2.Create(Self);
Form2.Show;
end;
non fa altro che aprire un istanza a Form2 e visualizzarla, la distruzione è delegata all Form2, hai qualche riferimento incrociato ?
di più nin so
G.
Ibis redibis non morieris in bello |
|
Goblin (Member)
Expert
Messaggi: 375
Iscritto: 02/02/2011
|
Postato originariamente da lorenzo:
il problema secondo me è la variabile locale.
Quando il form2 si apre, la variabile Form2 viene allocata nello spazio di memoria della funzione Click come variabile locale.
Una volta terminata la funzione la variabile viene eliminata con la sua memoria e, quando il form2 viene chiuso, non trova più la memoria correttamente associata e tenta di pulire lo spazio appartenente a qualcun altro. Da qui il messaggio di errore.
Per risolvere o dichiari Form2 come globale(inteso come variabile membro di Form1 che è la classe principale del progetto) oppure la crei come finestra Modale: in quest'ultimo caso Form2 deve essere chiuso PRIMA di uscire dalla funzione click e quindi il problema della memoria non si pone. |
mmmmm, allora
La variabile viene creata locale e gestita come tale, una volta invocato il metodo SHOW il comando passa alla form2, delphi7 non avendo la garbage collection non libera l'istanza alla form, la libera solo alla chiusura del owner, dunque sarà cura del programmatore liberare la memoria allocata per mezzo di una cafree nel close della form2.
Nel caso dichiari Form2 come variabile globale la logica del programma cambia, ossia: se la dichiari come variabile locale ad ogni click associ un istanza diversa e separata di form2 che vive di vita propria, se invece la dichiari come variabile globale devi stare molto attento a testare se già esiste l'istanza alla form altrimenti ti ritrovi che la tua variabile viene sovrascritta ad ogni click da una nuova istanza di Form2.
Nel caso di metodo modale, showmodal, non cambia molto in quanto non è stato messo nessun distruttore.
Riassumendo:
type
TForm1 = class(TForm)
...
private
Form2: TForm2;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(Self);
Form2.Show;
end;
In questo modo ad ogni click di button1 la variabile viene sovrascritta per evitare ciò:
procedure TForm1.Button1Click(Sender: TObject);
begin
if not(assigned(Form2)) then
Form2 := TForm2.Create(Self);
Form2.Show;
end;
ma così facendo fai un semplice show di una form creata in precedenza, con tutti i rischi che comporta....
....
procedure TForm1.Button1Click(Sender: TObject);
var Form2: TForm2;
begin
Form2 := TForm2.Create(Self);
Form2.Show;
end;
Ad ogni click di button1 viene generata una nuova istanza di form2 che sarà distrutta dall'owner (self) alla chiusura dell'applicativo a meno che non si lavora diversamente.
se poi vogliamo il modale
procedure TForm1.Button1Click(Sender: TObject);
var Form2: TForm2;
begin
Form2 := TForm2.Create(Self);
Form2.Showmodal;
end;
anche qui ...vedere un codice così .. direi .. orrore e ribrezzo... meglio scrivere
procedure TForm1.Button1Click(Sender: TObject);
begin
With TForm2.Create(Self) do
try
ShowModal;
finally
free;
end;
end;
In questo modo l'istanza creata di form2 viene distrutta all'uscita
dunque il problema è: Cosa vuole fare il nostro amico camaleonteplus ? e cosa c'e' scritto in form2?
di più nin so
G.
Ibis redibis non morieris in bello |
|