Samozwolnienie klasy TFrame.

0

Witam, mam klasę dziedziczoną od TFrame.
Problem polega na tym, że mam tam zdarzenie typu ButtonClick, w którym chciałbym zniszczyć ta klasę.

Próbowałem TFrame1.Destroy i TFrame1.Free. Za pierwszym razem działa, ale przy drugim wejściu do tej klasy, przy zwalnianiu wywala błąd.

Gdzieś czytałem, że przy zamykaniu klasy przez jej własną procedurę należy użyć Release, ja niestety nie posiadam tej opcji. Dodam jeszcze, że ta klasa jest utworzona w formularzu MainForm.

0

Próbowałem TFrame1.Destroy i TFrame1.Free.

Bezpieczniej jest zwalniać klasę przez Free, a jeśli potem może być znów wykorzystana (stworzona na nowo) to można wykorzystać FreeAndNil;

Za pierwszym razem działa, ale przy drugim wejściu do tej klasy, przy zwalnianiu wywala błąd.

Podaj treść błędu oraz wadliwy kod.

0

Project Project1.exe raised exceptions class EAccesViolations with message 'Access ciolation at adress 00436E9B in module 'Project1.exe'. Read of adress 01975494. Process stopped (...)

Definicja procedury powodującej błąd:

procedure TTableNewFrame.TableSave_ButtonClick(Sender: TObject);
var
  Result: String;
begin
  DB:= TDatabase.Create;
  TransToTable;
  DB.CheckExist('Table.dat');
  try
    DB.CreateTableFromArray(TableArray);
  except
    ShowMessage('Błąd.');
    Result:= 'False';
  end;
  if Result <> 'False' then
  begin
    ShowMessage('OK.');
    DB.Destroy;
    TableNewFrame.Free
  end;
end;

Jak już pisałem, próbuje zniszczyć klasę tej ramki poprzez procedurę w niej wywołaną, gdzieś czytałem że tak się nie da zrobić i trzeba użyć Release.
Niestety klasa TFrame nie posiada procedury Release.

EDIT: Poradziłem sobie już w inny sposób, poprzez ustawienie ramki jako niewidocznej, jednak wciąż jestem ciekaw jak wywołać zwolnienie tej klasy przez jej procedurę.

0

To może jeszcze wskażesz linię, w której wystąpił błąd..? Kod ten jest błędny, bo:

  • obiekt DB jest zwalniany jedynie wtedy, gdy warunek Result <> 'False' jest spełniony,
  • obiekt DB zwalniany jest przez Destroy, a powinien przez standardowe Free,
  • brak bloku try .. finally;
    To tak na szybko; Poza tym nie wiem po co wykorzystujesz ten dziwny Result, jak możesz wykonać odpowiednie operacje w bloku try .. except; Na dodatek DB jest pewnie globalne...
0

Już tłumaczę:

DB to jest globalna klasa odpowiedzalna za procedury związane z operacją na bazie danych.
Otóż używam procedury Destroy do obieków, przy których mam pewność, że zostaną zwolnione.
Przy except powinno być DB.Destroy, gdzieś mi umknęło.

W zasadzie ta procedura ma sprawdzać, czy nastąpiło poprawne zapisanie do tabeli, jeśli tak to ramka jest zamykana (obecnie ukrywana), jeśli nie to pozostaje w stanie w jakim była przed kliknięciem buttonu.
Result tutaj służy do powiadomienia czy wyjść z Frame'a. Nie mogłem tego uzyskać przez try ... finally.

1

DB to jest globalna klasa [...]

DB to globalny obiekt, nie klasa;

Przy except powinno być DB.Destroy, gdzieś mi umknęło.

No właśnie nie - zwalnianie obiektu ma być wykonane bez względu na to, czy wystąpi wyjątek czy nie; A tak to obiekt nie zawsze zostaje zwolniony i przy ponownej próbie utworzenia go wywala AV;

Result tutaj służy do powiadomienia czy wyjść z Frame'a. Nie mogłem tego uzyskać przez try ... finally.

Przecież Ci tłumaczę, że operacje po pojawieniu się wyjątku wykonuje się w bloku try .. except, a dokładnie pomiędzy except .. end, a nie poza tym blokiem; Z kolei blok try .. finally miał dbać o każdorazowe zwalnianie obiektu DB żeby uchronić przed błędami i wyciekami pamięci;

W zasadzie ta procedura ma sprawdzać, czy nastąpiło poprawne zapisanie do tabeli, jeśli tak to ramka jest zamykana (obecnie ukrywana), jeśli nie to pozostaje w stanie w jakim była przed kliknięciem buttonu.

procedure TTableNewFrame.TableSave_ButtonClick(Sender: TObject);
var
  DB: TDataBase;
begin
  DB := TDataBase.Create();

  try
    TransToTable();
    DB.CheckExist('Table.dat');

    try
      DB.CreateTableFromArray(TableArray);
      ShowMessage('OK.');
    except
      Self.Free();
      ShowMessage('Błąd.');
    end;
  finally
    DB.Free(); // lub FreeAndNil(DB), jeśli DB jest globalne
  end;
end;
0

Problem leży gdzie indziej, utworzyłem nowy button (Cancel), któremu przypisałem procedure z funkcją FreeAndNil(TableNewFrame).
Po pierwszym wejściu i wyjściu wszystko jest OK. Przy drugim wejściu a dokładniej przy kliknięciu na ten button wywala AV.

Może wina leży w module, który tworzy ten Frame?

procedure TTableFrame.TableNew_ButtonClick(Sender: TObject);
begin
  TableNewFrame:= TTableNewFrame.Create(MainForm);
  TableNewFrame.Parent:= MainForm;
  TableNewFrame.Top:= 40;
end;
0

Twój problem polega na tym że próbujesz do jednej zmiennej wsadzić całą listę różnych TTableNewFrame'ów.
Zmienną TableNewFrame wywal ręcznie aby nie kusiło.
Tam gdzie potrzebujesz stwórz zmienną lokalną:

procedure TTableFrame.TableNew_ButtonClick(Sender: TObject);
var TableNewFrame:TTableNewFrame;
begin
  TableNewFrame:= TTableNewFrame.Create(MainForm);
  TableNewFrame.Parent:= MainForm;
  TableNewFrame.Top:= 40;
end;
0

Podaj instrukcję, która powoduje AccessViolation bo dalej nic nie wiadomo; Uruchom debuger i jedź instrukcja po instrukcji (klawisz F7) aż wydupi AV i wtedy zaakceptuj komunikat, przerwij program (kombinacja Ctrl+F2), skopiuj linijkę, w której wystąpił błąd i wklej do posta; Tylko postaw sobie break point żebyś godzinę nie debugował po jednej instrukcji;

Poza tym - jak nazywa się formularz, na którym ma być ta ramka? Bo widzę, że w konstruktorze kontrolki podajesz jako rodzica MainForm, a przycisk, który służy do tworzenia tej ramki umiejscowiony jest na formularzu TTableFrame - dobrze rozumiem?
Chyba źle zrozumiałem...

0

Już wiem. Tak jak już pisałem wcześniej, klasę TFrame nie można zwalniać procedurą Destroy lub Free wywołaną z tej klasy.
Gdyby ktoś miał podobny problem: należy wysłać komunikat CM_RELEASE, który zwolni tą ramkę bez żadnych błędów typu AccessViolations.

0

NIE WOLNO używać metody Destroy! Nawet w helpie o tym piszą.

0

Przyjąłem to do wiadomości i pozamieniałem wszystkie procedury Destroy na Free.

1 użytkowników online, w tym zalogowanych: 0, gości: 1