动态创建的TImage,在关闭窗体时候报错,请问如何解决

时间:2021-05-13 19:14:35
动态创建的TImage,在关闭窗体时候报错,请问如何解决?加了释放代码 还是不行

创建代码:
    //新建立的图块基础属性设置
    img_tile := TImage.Create(GroupBox2);
    img_tile.Picture.Assign(loadImages[tmpImgID].imgByteData);
    img_tile.Transparent := true ;
    //新建立的图块编辑器属性设置
    img_tile.Parent := GroupBox2 ;
    img_tile.AutoSize := true ;
    img_tile.Visible := true ;



释放代码:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  i : Integer ;
  tmpImg : TImage;

begin
  for i:= 0 to GroupBox2.ControlCount-1 do
  begin
    //获取控件名Components[i].Name
    if GroupBox2.Controls[0] is TImage then
    begin
      tmpImg := TImage(GroupBox2.Controls[0]); //跟踪过了 全部释放
      FreeAndNil(tmpImg);
    end ;
  end;
end;




追踪了下确定是由于动态TImage问题引起的。 如果没创建TImage一切正常,一旦创建了TImage就算将其Free依然在关闭窗体时候报错?请问如何解决

24 个解决方案

#1


  if GroupBox2.Controls[0] is TImage then
   begin
   tmpImg := TImage(GroupBox2.Controls[0]); //跟踪过了 全部释放
   FreeAndNil(tmpImg);
   end ;
 应该是controls[i]

#2


GroupBox2.Controls[0],你一直用的是索引 0,那你还遍历有啥用,第一次被释放了,第二次肯定就不存在了,你还操作它肯定出错

#3


使用类似的
img_tile := TImage.Create(GroupBox2);代码,无需手动释放

如果使用
img_tile := TImage.Create(nil);
方式,就需要手动释放了。看看delphi源码就知道了。

#4


for i:= GroupBox2.ControlCount-1 downto 0 do
begin
  if GroupBox2.Controls[i] is TImage then
  begin
    TImage(GroupBox2.Controls[i]).free; 
  end ;
end;

#5


另外释放时也不要从0开始循环会出错的,应该逆序释放

#6


哇塞2,3,4L好几位大神啊,喝口水的功夫就被抢答了..........

#7


试了一下,没有你说的情况
估计是其他地方的问题

#8


引用 2 楼 bdmh 的回复:
GroupBox2.Controls[0],你一直用的是索引 0,那你还遍历有啥用,第一次被释放了,第二次肯定就不存在了,你还操作它肯定出错


基础问题,动态创建的控件删除是0还是i 照着代码试1遍不就知道了,不做多解释。

#9


引用 3 楼 smallhand 的回复:
使用类似的
img_tile := TImage.Create(GroupBox2);代码,无需手动释放

如果使用
img_tile := TImage.Create(nil);
方式,就需要手动释放了。看看delphi源码就知道了。


2种创建和释放的都试过 完全没效果

#10


引用 7 楼 m617105 的回复:
试了一下,没有你说的情况
估计是其他地方的问题


谢谢 我自己解决了确实不是这个问题引起的。

创建代码后面有一段给Record的代码赋值,是由于Record定义的变量位置引起的,
按道理来说不应该有此问题,由此我怀疑的Delphi的编译BUG。

原Record结构:
  // 图块数据
  TImgTileData = record
     id: Integer ;
     imgName : ShortString ; //图片名
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     imgPath : ShortString ; //路径
     level : Integer ; //所处图层
     logicSt : byte ; //逻辑状态
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
  end ;


改动后:
  // 图块数据
  TImgTileData = record
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
     id: Integer ;
     imgName : ShortString ; //图片名
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     imgPath : ShortString ; //路径
     level : Integer ; //所处图层
     logicSt : byte ; //逻辑状态

  end ;


我定义完全没变,只是改变了结构体的数据的排列方式,就OK了。

#11


1楼的回答过了。删除要从最后一个向前删除。
象你这种总是删除第一个不能用 for 循环,要用 while循环,其实用 while循环也不合适,因为得能保证
GroupBox2里只有 Timage类型才行。

#12


引用 11 楼 zyxip 的回复:
1楼的回答过了。删除要从最后一个向前删除。
象你这种总是删除第一个不能用 for 循环,要用 while循环,其实用 while循环也不合适,因为得能保证
GroupBox2里只有 Timage类型才行。

谢谢您的建议。 但是我觉得2种办法可能差不多

#13


引用 10 楼 huruihappy 的回复:
引用 7 楼 m617105 的回复:
试了一下,没有你说的情况
估计是其他地方的问题


谢谢 我自己解决了确实不是这个问题引起的。

创建代码后面有一段给Record的代码赋值,是由于Record定义的变量位置引起的,
按道理来说不应该有此问题,由此我怀疑的Delphi的编译BUG。

原Record结构:
  // 图块数据
  TImgTileData = reco……

。。。。。还有这情况????
难道是内存对齐的事???

#14


应该是这么回事,这个BUG很难找。

原先的这个连续存在3奇数不好对齐,估计被优化了
logicSt : byte ; //逻辑状态
isCanMov : Boolean ; //是否可以移动
isEnabled : Boolean ; //是否可用


后来改成了偶数,就再也木有报错了
isCanMov : Boolean ; //是否可以移动
isEnabled : Boolean ; //是否可用
id: Integer ;

#15


不可能吧。对其的问题一般在将结构用Socket发送时要注意,如果只是程序内部自己使用的不会有这种问题的。
更不可能是Delphi 的BUG。
你看到的可能只是表象。

#16


倒序释放是正确的。

#17


我找到的 就是这个record变量顺序问题,调整了下就OK

#18


找到问题了···低级错误···
TImgTileData = record
  id: Integer ;
  imgName : ShortString ; //图片名
  x: Integer; //X 坐标
  y: Integer; //Y 坐标
  w: Integer; //宽
  h: Integer; //高
  imgPath : ShortString ; //路径
  level : Integer ; //所处图层
  logicSt : byte ; //逻辑状态
  isCanMov : Boolean ; //是否可以移动
  isEnabled : Boolean ; //是否可用
  end ;


id不能作为record的首字段。···恶心啊

#19


楼主你这找出的原因怎么都奇怪的很啊。怎么id不能做首字段啊????????????

我的很多结构都是ID:Integer啊。

#20


好象要这样:
img_tile.Picture:=null;
freeandnil(img_tile);

#21


我就说说吧,首先楼主太浮躁,出现错误就怀疑是编译的BUG,遇到这种情况首先考虑自己程序的问题,其次不严谨:虽然删0和倒着删结果可能一样, 但是效率不一样,每次删0的话要把后面的存储内容Move到前面,再次是态度: 虽然不报错了,可还是有问题没有解决,为什么顺序会影响程序,难道仅仅是对其的原因么,我想这个没有解决好,下次遇到相同的情况还是会出错。恩..楼主既然找出原因了,我就不多说了,结贴吧.

#22


引用 21 楼 flcop 的回复:
我就说说吧,首先楼主太浮躁,出现错误就怀疑是编译的BUG,遇到这种情况首先考虑自己程序的问题,其次不严谨:虽然删0和倒着删结果可能一样, 但是效率不一样,每次删0的话要把后面的存储内容Move到前面,再次是态度: 虽然不报错了,可还是有问题没有解决,为什么顺序会影响程序,难道仅仅是对其的原因么,我想这个没有解决好,下次遇到相同的情况还是会出错。恩..楼主既然找出原因了,我就不多说了,结贴吧.


谢谢您,下次会注意的。。
我不介意你说我态度有问题,工程进度摆在那,很多东西不可能细想。
急的赶工程 所以也没细想太多东西。

那个ID出错的问题非常奇怪,但是我追踪内存错误地址回溯的时候,确实是找到的那个ID问题。 我用的是DELPHI XE。 我后来将ID改成IDEX,我代码其他部分都没变,又没有问题了。真的想不通为什么?请教下

  // 图块数据
  TImgTileData = record
//     id : Integer ;
     idex: Integer ;
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     logicSt : Integer ; //逻辑状态
     imgPathID : Short ;
     level : Short ; //所处图层
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
     isCustomLogic : Boolean ; //是否是自定义逻辑
  end ;

  //逻辑块数据
  TLogicTileData = record
//    id : Integer ;
    idex: Integer ;
    x: Integer; //X 坐标
    y: Integer; //Y 坐标
    w: Integer; //宽
    h: Integer; //高
    logicSt : Integer ;
    isCustomLogic : Boolean ;
    isEnabled : Boolean  ;
  end;

#23


没人知道?

#24


算了结贴给分,仍然没有找到这个问题的精准回答。

#1


  if GroupBox2.Controls[0] is TImage then
   begin
   tmpImg := TImage(GroupBox2.Controls[0]); //跟踪过了 全部释放
   FreeAndNil(tmpImg);
   end ;
 应该是controls[i]

#2


GroupBox2.Controls[0],你一直用的是索引 0,那你还遍历有啥用,第一次被释放了,第二次肯定就不存在了,你还操作它肯定出错

#3


使用类似的
img_tile := TImage.Create(GroupBox2);代码,无需手动释放

如果使用
img_tile := TImage.Create(nil);
方式,就需要手动释放了。看看delphi源码就知道了。

#4


for i:= GroupBox2.ControlCount-1 downto 0 do
begin
  if GroupBox2.Controls[i] is TImage then
  begin
    TImage(GroupBox2.Controls[i]).free; 
  end ;
end;

#5


另外释放时也不要从0开始循环会出错的,应该逆序释放

#6


哇塞2,3,4L好几位大神啊,喝口水的功夫就被抢答了..........

#7


试了一下,没有你说的情况
估计是其他地方的问题

#8


引用 2 楼 bdmh 的回复:
GroupBox2.Controls[0],你一直用的是索引 0,那你还遍历有啥用,第一次被释放了,第二次肯定就不存在了,你还操作它肯定出错


基础问题,动态创建的控件删除是0还是i 照着代码试1遍不就知道了,不做多解释。

#9


引用 3 楼 smallhand 的回复:
使用类似的
img_tile := TImage.Create(GroupBox2);代码,无需手动释放

如果使用
img_tile := TImage.Create(nil);
方式,就需要手动释放了。看看delphi源码就知道了。


2种创建和释放的都试过 完全没效果

#10


引用 7 楼 m617105 的回复:
试了一下,没有你说的情况
估计是其他地方的问题


谢谢 我自己解决了确实不是这个问题引起的。

创建代码后面有一段给Record的代码赋值,是由于Record定义的变量位置引起的,
按道理来说不应该有此问题,由此我怀疑的Delphi的编译BUG。

原Record结构:
  // 图块数据
  TImgTileData = record
     id: Integer ;
     imgName : ShortString ; //图片名
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     imgPath : ShortString ; //路径
     level : Integer ; //所处图层
     logicSt : byte ; //逻辑状态
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
  end ;


改动后:
  // 图块数据
  TImgTileData = record
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
     id: Integer ;
     imgName : ShortString ; //图片名
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     imgPath : ShortString ; //路径
     level : Integer ; //所处图层
     logicSt : byte ; //逻辑状态

  end ;


我定义完全没变,只是改变了结构体的数据的排列方式,就OK了。

#11


1楼的回答过了。删除要从最后一个向前删除。
象你这种总是删除第一个不能用 for 循环,要用 while循环,其实用 while循环也不合适,因为得能保证
GroupBox2里只有 Timage类型才行。

#12


引用 11 楼 zyxip 的回复:
1楼的回答过了。删除要从最后一个向前删除。
象你这种总是删除第一个不能用 for 循环,要用 while循环,其实用 while循环也不合适,因为得能保证
GroupBox2里只有 Timage类型才行。

谢谢您的建议。 但是我觉得2种办法可能差不多

#13


引用 10 楼 huruihappy 的回复:
引用 7 楼 m617105 的回复:
试了一下,没有你说的情况
估计是其他地方的问题


谢谢 我自己解决了确实不是这个问题引起的。

创建代码后面有一段给Record的代码赋值,是由于Record定义的变量位置引起的,
按道理来说不应该有此问题,由此我怀疑的Delphi的编译BUG。

原Record结构:
  // 图块数据
  TImgTileData = reco……

。。。。。还有这情况????
难道是内存对齐的事???

#14


应该是这么回事,这个BUG很难找。

原先的这个连续存在3奇数不好对齐,估计被优化了
logicSt : byte ; //逻辑状态
isCanMov : Boolean ; //是否可以移动
isEnabled : Boolean ; //是否可用


后来改成了偶数,就再也木有报错了
isCanMov : Boolean ; //是否可以移动
isEnabled : Boolean ; //是否可用
id: Integer ;

#15


不可能吧。对其的问题一般在将结构用Socket发送时要注意,如果只是程序内部自己使用的不会有这种问题的。
更不可能是Delphi 的BUG。
你看到的可能只是表象。

#16


倒序释放是正确的。

#17


我找到的 就是这个record变量顺序问题,调整了下就OK

#18


找到问题了···低级错误···
TImgTileData = record
  id: Integer ;
  imgName : ShortString ; //图片名
  x: Integer; //X 坐标
  y: Integer; //Y 坐标
  w: Integer; //宽
  h: Integer; //高
  imgPath : ShortString ; //路径
  level : Integer ; //所处图层
  logicSt : byte ; //逻辑状态
  isCanMov : Boolean ; //是否可以移动
  isEnabled : Boolean ; //是否可用
  end ;


id不能作为record的首字段。···恶心啊

#19


楼主你这找出的原因怎么都奇怪的很啊。怎么id不能做首字段啊????????????

我的很多结构都是ID:Integer啊。

#20


好象要这样:
img_tile.Picture:=null;
freeandnil(img_tile);

#21


我就说说吧,首先楼主太浮躁,出现错误就怀疑是编译的BUG,遇到这种情况首先考虑自己程序的问题,其次不严谨:虽然删0和倒着删结果可能一样, 但是效率不一样,每次删0的话要把后面的存储内容Move到前面,再次是态度: 虽然不报错了,可还是有问题没有解决,为什么顺序会影响程序,难道仅仅是对其的原因么,我想这个没有解决好,下次遇到相同的情况还是会出错。恩..楼主既然找出原因了,我就不多说了,结贴吧.

#22


引用 21 楼 flcop 的回复:
我就说说吧,首先楼主太浮躁,出现错误就怀疑是编译的BUG,遇到这种情况首先考虑自己程序的问题,其次不严谨:虽然删0和倒着删结果可能一样, 但是效率不一样,每次删0的话要把后面的存储内容Move到前面,再次是态度: 虽然不报错了,可还是有问题没有解决,为什么顺序会影响程序,难道仅仅是对其的原因么,我想这个没有解决好,下次遇到相同的情况还是会出错。恩..楼主既然找出原因了,我就不多说了,结贴吧.


谢谢您,下次会注意的。。
我不介意你说我态度有问题,工程进度摆在那,很多东西不可能细想。
急的赶工程 所以也没细想太多东西。

那个ID出错的问题非常奇怪,但是我追踪内存错误地址回溯的时候,确实是找到的那个ID问题。 我用的是DELPHI XE。 我后来将ID改成IDEX,我代码其他部分都没变,又没有问题了。真的想不通为什么?请教下

  // 图块数据
  TImgTileData = record
//     id : Integer ;
     idex: Integer ;
     x: Integer; //X 坐标
     y: Integer; //Y 坐标
     w: Integer; //宽
     h: Integer; //高
     logicSt : Integer ; //逻辑状态
     imgPathID : Short ;
     level : Short ; //所处图层
     isCanMov : Boolean ; //是否可以移动
     isEnabled : Boolean ; //是否可用
     isCustomLogic : Boolean ; //是否是自定义逻辑
  end ;

  //逻辑块数据
  TLogicTileData = record
//    id : Integer ;
    idex: Integer ;
    x: Integer; //X 坐标
    y: Integer; //Y 坐标
    w: Integer; //宽
    h: Integer; //高
    logicSt : Integer ;
    isCustomLogic : Boolean ;
    isEnabled : Boolean  ;
  end;

#23


没人知道?

#24


算了结贴给分,仍然没有找到这个问题的精准回答。