OpenDialog的奇怪问题:第二次打开时出现非法内存访问

时间:2021-04-27 18:15:39
当第二次执行如下代码时,在标注了的地方出现非法内存操作。跟踪进去看cpu信息,发现它抛出了一个异常,大家帮忙看看。(另一段也是按钮打开这个打开文件对话框,没有问题)

procedure TForm1.Button3Click(Sender: TObject);
var
  TempleteName:TStringList;
  i           :integer;
begin
  TempleteName := TStringList.Create;

  if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
    TempleteName := (OpenDialog1.Files) as TStringList;
    if TempleteName.Count <> 0 then
    begin
      for i := 0 to TempleteName.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(TempleteName[i]));
    end;
  end;
  TempleteName.Free;
end;

20 个解决方案

#1


没看出程序有什么错:(

#2


我找不到一个什么理由!

#3


TempleteName将opendialog1给FREE掉了,它们指向同一对像...

#4


我试了你的程序, 连续两次按都没问题, 只是在程序退出时出错

#5


没有理由不正确(这段代码)

#6


可能是delphi的问题

#7


同意gzyzljk(正龙剑客)
TempleteName := () as TStringList;
////
try;
TempleteName.Assign(OpenDialog1.Files) ;

#8


怎么指向同一对象?

#9


刚才有别的程序参与, 我又重建了一个程序, 再试, 真的就出现了你说的问题了, 好怪

#10


程序我看了一天了,本身没有什么问题。也新开了一个project试,就没有出现。

Drate(鸟窝里的虫) :找不到理由,呵呵,但它确实出现了。

gzyzljk(正龙剑客) :TempleteName在free时,只会free自己吧,我把它按值复制再看看。

xirumin(吃好喝好) :我的在退出时也有问题。看来的确是Free掉了不该Free的东西。

大家再看看还有什么原因。

#11


谢谢outer2000(天外流星)与gzyzljk(正龙剑客)
改成Assign赋值就没有问题了。

看来 TempleteName := (OpenDialog1.Files) as TStringList;这样用是不对的。的确是指象了OpenDialog1这个对像。

谢谢各位,回头我再补补VCL知识。

#12


TempleteName := (OpenDialog1.Files) as TStringList;
很明显的,你把OpenDialog1对象的一块内存区域指针赋值给了TempleteName
而后你有调用TempleteName.Free释放该内存空间的的这个TStringList对象
这个对象是OpenDialog1内含的,当第2次调用OpenDialog1.Execute 时,OpenDialog1要访问该TStringList,但是此时该对象已经被你释放掉了,当然出错了。
把TempleteName := (OpenDialog1.Files) as TStringList;
改为:
TempleteName.Assign(TStringList(OpenDialog1.Files));

#13


错了,根本不用强制转换
TempleteName.Assign(OpenDialog1.Files);

#14


上面有人答对了!

#15


procedure TForm1.Button3Click(Sender: TObject);
var
  TempleteName:TStringList;
  i           :integer;
begin
 if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
    TempleteName := (OpenDialog1.Files) as TStringList;
    if TempleteName.Count <> 0 then
    begin
      for i := 0 to TempleteName.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(TempleteName[i]));
    end;
  end;
end;

#16


不用TStringList也行
var
//  TempleteName:TStringList;
  i           :integer;
begin
//  TempleteName := TStringList.Create;

  if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
 //   TempleteName := TStrings(OpenDialog1.Files);
    if OpenDialog1.Files.count <> 0 then
    begin
      for i := 0 to OpenDialog1.Files.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(OpenDialog1.files[i]));
    end;
  end;

#17


pazee(耙子) 老大真搞笑,把我的那句Free删掉完事了。:-)

#18


var
  TempleteName:TStringlist;
  i           :integer;
begin
  TempleteName := TStringlist.Create;
  if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
   try
 TempleteName.AddStrings(OpenDialog1.Files);
    if TempleteName.Count <> 0 then
    begin
      for i := 0 to TempleteName.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(OpenDialog1.Files[i]));
    end;
  finally
  TempleteName.Free;
  end;
  end;
end;

#19


to 无名:
不是高效,

  TempleteName := TStringList.Create;
  ....
  TempleteName := (OpenDialog1.Files) as TStringList;

这两句的结果势必会造成内存泄漏!

TStringList.Create这代码申请的内存你给弄丢了。

#20


to zwjchina(蒲石)  把OpenDialog1对象的一块内存区域指针赋值给了TempleteName  //一块内存区域指针你指的是不是OpenDialog1对象的一部分内存区域指针

#1


没看出程序有什么错:(

#2


我找不到一个什么理由!

#3


TempleteName将opendialog1给FREE掉了,它们指向同一对像...

#4


我试了你的程序, 连续两次按都没问题, 只是在程序退出时出错

#5


没有理由不正确(这段代码)

#6


可能是delphi的问题

#7


同意gzyzljk(正龙剑客)
TempleteName := () as TStringList;
////
try;
TempleteName.Assign(OpenDialog1.Files) ;

#8


怎么指向同一对象?

#9


刚才有别的程序参与, 我又重建了一个程序, 再试, 真的就出现了你说的问题了, 好怪

#10


程序我看了一天了,本身没有什么问题。也新开了一个project试,就没有出现。

Drate(鸟窝里的虫) :找不到理由,呵呵,但它确实出现了。

gzyzljk(正龙剑客) :TempleteName在free时,只会free自己吧,我把它按值复制再看看。

xirumin(吃好喝好) :我的在退出时也有问题。看来的确是Free掉了不该Free的东西。

大家再看看还有什么原因。

#11


谢谢outer2000(天外流星)与gzyzljk(正龙剑客)
改成Assign赋值就没有问题了。

看来 TempleteName := (OpenDialog1.Files) as TStringList;这样用是不对的。的确是指象了OpenDialog1这个对像。

谢谢各位,回头我再补补VCL知识。

#12


TempleteName := (OpenDialog1.Files) as TStringList;
很明显的,你把OpenDialog1对象的一块内存区域指针赋值给了TempleteName
而后你有调用TempleteName.Free释放该内存空间的的这个TStringList对象
这个对象是OpenDialog1内含的,当第2次调用OpenDialog1.Execute 时,OpenDialog1要访问该TStringList,但是此时该对象已经被你释放掉了,当然出错了。
把TempleteName := (OpenDialog1.Files) as TStringList;
改为:
TempleteName.Assign(TStringList(OpenDialog1.Files));

#13


错了,根本不用强制转换
TempleteName.Assign(OpenDialog1.Files);

#14


上面有人答对了!

#15


procedure TForm1.Button3Click(Sender: TObject);
var
  TempleteName:TStringList;
  i           :integer;
begin
 if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
    TempleteName := (OpenDialog1.Files) as TStringList;
    if TempleteName.Count <> 0 then
    begin
      for i := 0 to TempleteName.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(TempleteName[i]));
    end;
  end;
end;

#16


不用TStringList也行
var
//  TempleteName:TStringList;
  i           :integer;
begin
//  TempleteName := TStringList.Create;

  if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
 //   TempleteName := TStrings(OpenDialog1.Files);
    if OpenDialog1.Files.count <> 0 then
    begin
      for i := 0 to OpenDialog1.Files.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(OpenDialog1.files[i]));
    end;
  end;

#17


pazee(耙子) 老大真搞笑,把我的那句Free删掉完事了。:-)

#18


var
  TempleteName:TStringlist;
  i           :integer;
begin
  TempleteName := TStringlist.Create;
  if OpenDialog1.Execute then       //当点第二次时就在这里出现非法内存操作
  begin
   try
 TempleteName.AddStrings(OpenDialog1.Files);
    if TempleteName.Count <> 0 then
    begin
      for i := 0 to TempleteName.Count -1 do
        TreeView4.Items.Add(nil,ExtractFileName(OpenDialog1.Files[i]));
    end;
  finally
  TempleteName.Free;
  end;
  end;
end;

#19


to 无名:
不是高效,

  TempleteName := TStringList.Create;
  ....
  TempleteName := (OpenDialog1.Files) as TStringList;

这两句的结果势必会造成内存泄漏!

TStringList.Create这代码申请的内存你给弄丢了。

#20


to zwjchina(蒲石)  把OpenDialog1对象的一块内存区域指针赋值给了TempleteName  //一块内存区域指针你指的是不是OpenDialog1对象的一部分内存区域指针

#21