showmodal显示窗体,关闭时内存报错。请问各位知道原因么?
创建的时候用的 
  if not assigned(form1) then
   begin
    form1:=Tform1.create(application);
    form1.showmodal;
   end;
关闭时在close里写
 action:=cafree;
 form1:=nil;
各位帮忙看看。

解决方案 »

  1.   

    关闭时在close里写 
    action:=cafree; 
    form1:=nil; 谁的close事件
      

  2.   

    做的测试:两个form,form2为主窗体,在form2的create事件里写
    if not assigned(form1) then 
      begin 
        form1:=Tform1.create(application); 
        form1.showmodal; 
      end; 
    在form2的close事件里写
    action:=cafree; 
    form1:=nil; 没有问题
      

  3.   

    做了测试,没有出错
    form1:=nil; 可以不写
      

  4.   

    窗口事件中不能对自已 给 nil值啊但如果你 不给 nil你这程序可能退出时会报错将Application 换成 nil 就可以Free不nil了
      

  5.   

    这类用一次就丢的标准代码为同时将其从工程的自动创建列表中去掉with TFormX.Create(self) do
    try
      Showmodal;
    finally
      Free;
    end;
      

  6.   


      if not assigned(form1) then   //不要用這種方法判斷。  form1:=nil;   // 在類的關閉事件裏,不要帶入引用變量。 
    不過你上面的代碼應該是沒有錯的。 你貼出錯來,應該是別的地方引起的。 
      
      

  7.   


    form1.showmodal; 
    //直接跟free就好了
    //Showmessage('什么时候下去');  你会发现窗体关闭后才往下走
    form1.free;
      

  8.   

    form1:=nil; 
    要寫在ondestroy事件里面
    begin
      inherited;
      form1:=nil; 
    end;設定cafree後-----調用release--->free---->構造函數Destroy,這里會去遍歷application,執行removecomponent,將自己從components屬性list中移除。
    所以你在之后設定form1:=nil,執行free時,不會觸發destroy,會造成components無法被正確維護,在之后的訪問過程中,就出現地址訪問非法的問題。所以應該寫在ondestroy里面。建議在create對象時,能不傳參數就不傳,傳nil。這樣效能上面肯定比較好,因為不必再去維護owner.components。
      

  9.   

    上面說的“遍歷application”,是因為你create時傳的是appllication
      

  10.   

    不知道说啥好了……你觉得 OnDestroy 事件里的 inherited 会执行什么?procedure FormDestroy(Sender: TObject) 和 destructor Destroy 之间是什么关系?
    像下面的 Free 能触发 destructor Destroy 么?会出任何现访问错误么?  form1 := nil;
      with TForm1.Create(Application) do
      try
        ShowModal;
      finally
      end;
    ...procedure TForm1.FormClose(Sender: TObject);
    begin
      form1 := nil; {*}
      Free; { 已经在设计期使 OnClose = FormClose }
    end;如果前面用 form1 := TForm1.Create(Application),那么*那句会造成什么影响?或者program Project1;uses
      Forms,
      Unit1;procedure CreateMainForm;
    var t: Cardinal;
    begin
      Application.CreateForm(TForm1, t);
    end;begin
      Application.Initialize;
      CreateMainForm;
      Application.Run;
    end.
    unit Unit1;interfaceuses
      Forms;type
      TForm1 = class(TForm)
      end;implementation{$R *.dfm}end.
    {==== Unit1.dfm ====}
    object blah: TForm1
    end像这样的程序能正确执行么?会有什么诸如Application无法正确维护出现访问错误的不良后果么?
    btw,注意在 Unit1 中连 var Form1: TForm1 的声明都没有
      

  11.   

    楼上的,
    1、先搞清楚我要说的是什么,application只是一个例子,因为是作为参数传进取,只要是Tcomponent类型的!
    2、把相关源代码先看清楚;
    3、要驳倒我的观点,请拿出具有可比性的东西!不要在没搞清问题前就在这“发飚”,我可没那么多时间陪你 耍
      

  12.   

    真了不起,您自己胡说八道了一堆,连oo的基本机制都没搞清楚,还反过来让别人去读源代码
    答案是:Destroy是Destroy,FormDestroy是FormDestroy,两者没关系,OnDestroy里写一句inherited什么都不会发生。delphi的对象不需要靠外部变量去维护,它自己可以通过Self指针正确处理。后面我举的几个例子就是为了说明,不论什么何时设定 form1:=nil 甚至不要form1这个变量,都不会影响vcl的运作机制。所以你说的一堆不会触发这个那个,什么不会被正确维护、地址访问错误之类的都是扯淡,谁希罕跟您“发飚”么?
      

  13.   

    看了各位的说法,有点疑问:
    1: if not assigned(form1) then  //不要用這種方法判斷。 
       为什么不能用这种方法判断?
    2:我的程序中有第三方控件,是不是有可能是因为第三方控件的原因才导致内存错误?
    3:如果是show窗体的话。该怎么释放?
      

  14.   

    1: assigned(form1) 窗体没nil掉就会异常
    2:不大可能 
    3:OnClose事件里写个Realse;方便简单
      

  15.   

    if Assigned(Form1) then   
    和   
    if Form1<>nil then      
          
    Assigned是判断指针所指向的内容是否为空。如果Form1指向的内容(即对象)被释放,但没有把Form1赋成nil的话,则会出现下列的情况:   
    Assigned(Form1)返回false   
    而Form1<>nil返回true   
    可见是不等价的,如果Form1是一个全局变量的话,释放Form1用Form1.free是不严格的,应该用FreeAndNil(Form1);
      

  16.   

    1:按F7单步执行时,怎么能跳出第三方控件的代码,转到自己的代码里去。
    2:if not assigned(form1) then form1:=Tform1.create(application) 和 with TForm1.Create(self)的区别。
      

  17.   

    再考虑一下其它原因,问题不在这段代码上,可能是有些对象没有析构或什么的。把窗口中的其它必须执行的代码先注释掉不出错后再慢慢恢复。上面的方法我放在另一个帖中,没被人重视。楼主为什么不重建一个新form,把你说的那些认为有问题的代码写进去看会不会出错,不要无原则的试来试去。
      

  18.   

    Tform1.create(application) 和 TForm1.Create(self)所有者,没什么大区别.做下简单试验就知道了
      

  19.   

    为啥这么多人喜欢乱讲呢,你试过自己说的么?Assigned(p) 完全等价于 p<>nil,你觉得能delphi通过什么机制检查出一个地址是不是被“释放”了?
    1. 删掉编译好的dcu,用 dcc32.exe -q *.pas -z -$D- 重新编译
    2. 如果是关于with,随便找本书应该都有说;如果是问TForm.Create(AOwner: TComponent)的差别,那么见vcl源代码constructor TComponent.Create(AOwner: TComponent);
    begin
      FComponentStyle := [csInheritable];
      if AOwner <> nil then AOwner.InsertComponent(Self);
    end;也就是说,当指定为AOwner的控件被释放的时候,该控件也被释放了。虽然一般情况下ShowModal里不会放什么奇怪的代码,Create(Self/Application/nil)看起来没什么差别(一般都是在窗体事件中,Self指向的是一个TForm的继承对象),但是像下面这段代码就可以挂掉用Create(Self)的程序(由于模式窗体的作用,程序将没法再得到响应):{Unit1.pas}
    ...
    implementationuses
      Unit2;procedure TForm1.Button1Click(Sender: TObject);
    begin
      if(not Assigned(Form2))then
        Form2 := TForm2.Create(Application);
      Form2.Show;
    end;=================================================
    {Unit2.pas}
    ...
    implementationuses
      Unit3;procedure TForm2.Button1Click(Sender: TObject);
    begin
      with TForm3.Create(Self) do { 换成Application/nil则没问题 }
      try
        ShowModal;
      finally
        Free;
      end;
    end;=================================================
    {Unit3.pas}
    ...
    implementationuses
      Unit2;procedure TForm3.Button1Click(Sender: TObject);
    begin
      FreeAndNil(Form2);
    end;ps:使用环境为d7。如果设计vcl的时候考虑到的话,也有较复杂的办法可以避免这种情况发生,不知道后面版本的delphi有没有在vcl中“修正”这个“bug”
      

  20.   


    你自己试试有没有Form1赋成nil的结果再来说
      

  21.   

    你要我试啥?你的命题是:
    Assigned(p) 和 p<>nil 不等价,按照你的说法,会出现 Assigned(Form1)为False 并且 Form1<>nil为True 的情况
    还是你构造一个这种情况出来吧要不,我这儿给您一段代码,您亲自试试看自己是不是胡说?procedure TForm1.Button1Click(Sender: TObject);
    const
      B2S : array[Boolean]of string = ('False', 'True');
    var
      o : TObject;
    begin
      o := TButton.Create(nil);
      o.Free;
      Memo1.Lines.Add(B2S[Assigned(o)]);
      Memo1.Lines.Add(B2S[o<>nil]);
    end;