Dynamiczna tablica obiektów i błędne dane

0

Wydaje mi się że problem jest banalny ale sam nie potrafię tego rozwiązać. Tworzę obiekty i przypisuje do nich dane, obiekty wrzucam do dynamicznej tablicy. Wszystko jest właściwie ok do momentu kiedy chcę zwolnić obiekt po przepisaniu go do tablicy. Dane się rozwalają i wyświetlają losowo. Sprawdzałem podczas debugowania że problem leży właśnie przy zwalnianiu obiektu :/ Kiedy wywalę z kodu usuwanie obiektu wszystko działa ok ale wydaje mi się że powinienem usunąć obiekt. Zamieszczam poniżej prosty kod co chcę zrobić. Działa dokładnie jak u mnie czyli źle :] (dane są podmieniane przy zwolnieniu obiektu lub podczas dostępu do tablicy i próby ich wypisania). Jest jeszcze kwestia tego że błędy występują zawsze w tym samym miejscu :) Kiedy mam tablicę jednoelementową (jeden obiekt) wtedy albo wszystkie dane są zwalone albo pierwsza (dane jako zmienne w obiekcie). Dla tablicy > 1 element problem dotyczy ostatniej wartości ostatniego obiektu w tablicy lub ostatnich wartości w ostatnim obiekcie. Gdzie leży błąd?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  Tobiekt = class
    par1 : Integer;
    par2 : Double;
    par3 : Integer;
  end;

  Tobiekt2 = class
    war1 : Double;
    war2 : Integer;
    war3 : Double;
  end;

var
  Form1: TForm1;
  obiekt1 : Tobiekt;
  obiekt2 : Tobiekt2;
  TabObiekt : array of Tobiekt;
  TabObiekt2 : array of Tobiekt2;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i, k, size : Integer;
  
begin
SetLength(TabObiekt, 0);
SetLength(TabObiekt2, 0);
k := 0;
for i := 0 to 1 do
  begin
  obiekt1 := Tobiekt.Create;
    with obiekt1 do
    begin
      par1 := k;
      Inc(k);
      par2 := k;
      Inc(k);
      par3 := k;
      Inc(k);
      size := high(tabobiekt) + 2;
    end;
    SetLength(TabObiekt, size);
    TabObiekt[ High(tabobiekt) ] := obiekt1;
  end;
  obiekt1.Free;


for i := 0 to 0 do
  begin
  obiekt2 := Tobiekt2.Create;
    with obiekt2 do
    begin
      war1 := k;
      Inc(k);
      war2 := k;
      Inc(k);
      war3 := k;
      Inc(k);
      size := high(tabobiekt2) + 2;
    end;
    SetLength(TabObiekt2, size);
    TabObiekt2[ High(tabobiekt2) ] := obiekt2;
  end;
  obiekt2.Free;


for i := 0 to high(tabobiekt) do
  begin
    Memo1.Lines.Add('Obiekt 1: ' + IntToStr(tabobiekt[i].par1));
    Memo1.Lines.Add('Obiekt 1: ' + FloatToStr(tabobiekt[i].par2));
    Memo1.Lines.Add('Obiekt 1: ' + IntToStr(tabobiekt[i].par3));
  end;

for i := 0 to high(tabobiekt2) do
  begin
    Memo1.Lines.Add('Obiekt 2: ' + FloatToStr(tabobiekt2[i].war1));
    Memo1.Lines.Add('Obiekt 2: ' + IntToStr(tabobiekt2[i].war2));
    Memo1.Lines.Add('Obiekt 2: ' + FloatToStr(tabobiekt2[i].war3));
  end;

  Memo1.Lines.Add('');

end;

end.
0

Nie wnikam dokładnie ale po co klasa...
Do tych danych co masz to wystarczy rekord.

SetLength(TabObiekt, 0);

Alokujesz pamięć dla zero elementów ? :-)

0

Racja z tą klasą. Zmieniłem na rekord i jest ok. Dzięki :) Ale dalej pytanie dlaczego nie działa to z klasą?

Odnośnie alokacji dla 0 - wszystko jest przypisane do buttona. Bez tego po każdej iteracji tablica się powiększa. A mi chodziło żeby pokazać problem konkretnie dla tablicy 1 i 2 elementowej.

ps. to tylko prosty przykład miał być żeby pokazać co i jak

0

przypisanie TabObiekt2[ High(tabobiekt2) ] := obiekt2; NIE KOPIUJE obiektu a jedynie WSKAŹNIK do niego. Jak potem zrobisz obiekt2.Free to jest to dokładnie to samo jakbyś zrobił TabObiekt2[ High(tabobiekt2) ].Free więc jak to ma działać

Clarc napisał(a)

Odnośnie alokacji dla 0 - wszystko jest przypisane do buttona. Bez tego po każdej iteracji tablica się powiększa. A mi chodziło żeby pokazać problem konkretnie dla tablicy 1 i 2 elementowej.

Taką tablicę trzeba zwalniać inaczej -

for i := 0 to Length(tabobiekt) - 1 do
  tabobiekt[i].Free;
SetLength(TabObiekt, 0);

a do takich rzeczy to najlepiej nadaje się TObjectList (albo samo TList)

0
Misiekd napisał(a)

przypisanie TabObiekt2[ High(tabobiekt2) ] := obiekt2; NIE KOPIUJE obiektu a jedynie WSKAŹNIK do niego.
...
a do takich rzeczy to najlepiej nadaje się TObjectList (albo samo TList)

W jaki sposób można w takim razie przypisać/skopiować jakieś dane (nie przez wskaźnik)? W TList też mam jedynie odwołanie do wskaźnika (chyba że chodziło tylko o odwołanie do odpowiedniej wartości). Mam wykonywane obliczenia w wątkach i przepisywane wyników do zmiennych wewnątrz wątku. Po zakończeniu obliczeń chcę przepisać te wyniki 'na zewnątrz' i zwolnic wątek. Jeśli nie przez tablicę to jak inaczej?

0

aby można było kopiować obiekty trzeba

  1. dziediczyć go po TPersistent
  2. zaimplementować kopiowanie tego co chcesz w metodzie Assign
    a potem robisz tak

ob1.Assign(obj2)

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