掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
配列をこのフォームのメンバーにするには? (ID:15092)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
回答ではありませんが。。。 > type > AAARecord = record > Edit2: String; > end; レコード型のメンバにString型があるとき、そのString型のメモリの開放がうまくいかないんじゃなかったかなと。 SetLengthで、要素数が減る場合、減る分の要素に対して Edit2 := '' とかして、文字列への参照を無くしておかないといかんかった気がする。 この辺は、過去ログあたりにもあるのかもしれないが、良ければ識者の方、教えてください。 [その他つっこみ] > procedure TForm1.Button2Click(Sender: TObject); > var > editString: String; > begin > editString := Edit1.Text; > Form2.Setedit1(editString); > Form2 := TForm2.Create(nil); > Form2.ShowModal; > end; Form2のインスタンスがクリエイトされる前に、Form2のメソッドSetedit1を使っている。 普通はエラーになるが、Form2の自動生成がOnになっており、かつ、 > var > Form2: TForm2; > > implementation このように、自動で作成されるグローバルな変数 Form2が存在するため、エラーにならない。 しかも、Form2のクリエイトのパラメータがnilのため、自動破棄されない。 いわゆるメモリーリークになる。 Form1のButton2をたたけばたたくほど、見えないForm2のインスタンスが次々作成されていく。 タスクマネージャーを起動し、Form1のButton2を連打しまくれば、使用メモリが次々増えていく様子を確認することができるでしょう。 ただし、Form2.OnCloseでAction = caFree としているなら、メモリーリークは発生しない。 発生しないが、 > Form2.Setedit1(editString); ここで、破棄されたForm2のインスタンスにアクセスすることになり、結局エラーになるわけだ。 一般には、以下のように書くのが望ましいでしょう。 必要に応じて例外処理を記述すること。 procedure TForm1.Button2Click(Sender: TObject); var editString: String; xxForm2: TForm2; begin editString := Edit1.Text; xxForm2:= TForm2.Create(Self{nil}); xxForm2.Setedit1(editString); xxForm2.ShowModal; xxForm2.Free; //または //xxForm2.Releace; end; 次 > procedure TForm2.Setedit1(edit1: String); > begin > Str := Edit1; > end; コンポーネントにも Edit1 があり、まぎらわしい。 今回は、引数の型がStringであるため大事に至らないが、バグの元である。 さらに次 > procedure TForm2.FormShow(Sender: TObject); > var i: Integer; > begin > Edit1.Text := str; > for i := Low(aaaArr) to High(aaaArr) do > begin > if Edit1.Text = Form1.ListBox1.Items[Form1.ListBox1.ItemIndex] then > begin > Edit2.Text := aaaArr[i].Edit2; > end; > end; > end; 配列aaaArrのサイズとForm1.ListBox1のアイテム数が一致している保証がない。 最初のうちは、配列aaaArrのサイズが0のため、「Indexが範囲を超えています」というメッセージに遭遇していないだけです。 結論 やりたいことがわからない。 Unit2のユニット変数にしないで、TFormの変数にしてしまったほうが楽。 また、前述の通り、Record型のメンバにString型がある場合、メモリの行方が気になる。 今回、String型一つだけなので、むしろTStringListを使った方が吉。 勉強中だから、どうしても使いたいというのであれば、以下のようにするとイイかもな。 ----------------------------------------------- type TArrayAAARecord = array of AAARecord; funstion GetUnit2ArrayAAARecord: TArrayAAARecord; implementation > var > str: String; > //aaaArr: array of AAARecord; aaaArr: TArrayAAARecord; funstion GetUnit2ArrayAAARecord: TArrayAAARecord; begin Result := aaaArr; end; ----------------------------------------------- これで、GetUnit2ArrayAAARecordを使って配列を拾っておけば、メンバとして使えるでしょう。 ただし、array of HogeHoge のような動的配列は、暗黙ポインタ型。 例えば、以下のようにした場合、AとBは同じ内容(ポインタ)をさす。 したがって、実行結果は A[0] = 2 = B[0] var A, B: array of Integer; begin SetLength(A, 1); A[0] := 1; B := A; B[0] := 2; end; じゃ、こっちはどうなる? var A, B: array of Integer; begin SetLength(A, 1); B := A; SetLength(A, 2); //これって B = A なの? end; やったことがないので知りません。 実行結果が常に B = A なるのであれば、上記のTArrayAAARecord型宣言の方式で十分要求を満たすでしょう。 あとは、自分でやるべし。
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.