Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: 呼び出し元のフォームのメモリ解放後に別の画面を表示させることについて


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 2 - Last Post: Jun 21, 2014 4:58 PM Last Post By: Eri MATSUURA
Eri MATSUURA

Posts: 2
Registered: 7/14/14
呼び出し元のフォームのメモリ解放後に別の画面を表示させることについて  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 14, 2014 4:54 PM
下記のようなコードを書きました。
Form2に割り当てられたすべてのメモリを解放した後で、Form3を表示させようとすると、
Form3のOnShowイベント内でMessageDlgを表示させようとした場合にAccessViolationが発生します。
Form3表示時点でForm2のインスタンスが消滅していることが原因でAccessViolationが発生するのではないかと考えていますが、
MessageDlgを表示させなかった場合は、AccessViolationは発生せず、Form3を表示することができます。

MessageDlgを表示させることによって、Form描画時に発生している影響は何かあるのでしょうか?
(Form3表示後にForm2に割り当てられたメモリを解放することが正しい書き方だとは思いますが、
フォーム表示中にMessageDlgを出すとAccessViolationが発生する原因を理解したいです。)

void __fastcall TForm2::Button1Click(TObject *Sender)
{
    Close();
    TForm3* Form3= new TForm3(Application); 
    Form3->Show();
}
 
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
    Action= caFree;
    Form2 = NULL;
}
Hiroshi Honda

Posts: 3
Registered: 6/20/07
Re: 呼び出し元のフォームのメモリ解放後に別の画面を表示させることについて  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 17, 2014 5:55 PM   in response to: Eri MATSUURA in response to: Eri MATSUURA
Form3のスコープの問題じゃないでしょうか。
この書き方だとButton1Clickを抜けるとForm3は破棄されると思います。
実際にはForm3のインスタンスがすぐにクリアされるわけではないと思いますので
Form3のOnShowイベントなどで何もしない場合は破棄される前に表示までたどり着き
OnShowイベントでダイアログ表示などいろいろ処理をしてForm3に戻ろうとしたときには
Form3が破棄されてしまって(もしかしたらForm2の破棄までされて)いて
AccessViolationになるんじゃないかと想像します。
ダイアログを表示しないときにForm3が表示されるのも、たまたまだと思います。

なので、回避策としてはForm3変数の宣言だけグローバルもしくは
Form2のスコープの外にすればいいのではないでしょうか。
つまり
TForm3* Form3;
これだけ、どこか他の(適切な)部分で宣言し
Button1Clickイベントでは
Form3 = new TForm3(Application);
だけにすれば大丈夫だと思います。

もっとも私は普段Delphi使いで、最近のC++の記述に詳しくないので
もっと適切な書き方があるのかもしれませんが、基本的な概念は同じでしょう。

Eri MATSUURA wrote:
下記のようなコードを書きました。
Form2に割り当てられたすべてのメモリを解放した後で、Form3を表示させようとすると、
Form3のOnShowイベント内でMessageDlgを表示させようとした場合にAccessViolationが発生します。
Form3表示時点でForm2のインスタンスが消滅していることが原因でAccessViolationが発生するのではないかと考えていますが、
MessageDlgを表示させなかった場合は、AccessViolationは発生せず、Form3を表示することができます。

MessageDlgを表示させることによって、Form描画時に発生している影響は何かあるのでしょうか?
(Form3表示後にForm2に割り当てられたメモリを解放することが正しい書き方だとは思いますが、
フォーム表示中にMessageDlgを出すとAccessViolationが発生する原因を理解したいです。)

void __fastcall TForm2::Button1Click(TObject *Sender)
{
    Close();
    TForm3* Form3= new TForm3(Application); 
    Form3->Show();
}
 
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
    Action= caFree;
    Form2 = NULL;
}
Eri MATSUURA

Posts: 2
Registered: 7/14/14
Re: 呼び出し元のフォームのメモリ解放後に別の画面を表示させることについて  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 21, 2014 4:58 PM   in response to: Hiroshi Honda in response to: Hiroshi Honda
Hiroshi Honda さま

ご回答ありがとうございました。

ダイアログを表示しないときにForm3が表示されるのも、たまたまだと思います。

おそらくForm3表示時にForm3, Form2が破棄されてしまっていてAccessViolarionが発生するということが
あるのではないかということが理解できてよかったです。

(現在、アドバイスを基に、TForm3* Form3をグローバルにした別のプログラムを書きました。
今度は、Form3表示時にAbstractエラーが発生する場合があります。
このプログラムエラー発生個所を探ると、テキストファイル読み込み処理を通した後に
Form3を(OnShowイベントでダイアログ表示して)表示させると、Abstractエラーになってしまいます。
問題が変わってきてしまったと思いますので、
この件につきましては、当方ではっきり再現できる現象を調査し、まとめたうえで、別の質問としたいと思います。)

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02