【发布时间】:2014-08-31 13:04:12
【问题描述】:
我在我的一个项目中遇到了一些奇怪的问题。最奇怪的是,这只发生在这个项目中,我不能在另一个项目中重新创建它。
幸运的是,这是一个小项目(旨在为 SO 上的一个问题提供答案 - 仍未完成)所以我设法弄清楚它必须做一些事情来破坏我放置在我的 TImage 组件在设计时形成并在设计时为其设置 BMP 图像。
我得到的 AV 是: Project Project1.exe 引发异常类 $C0000005,并带有消息“在 0x00407430 处访问违规:读取地址 0xfffffffc”。
最后三个调用堆栈是:
Vcl.Graphics.TBitmapCanvas.Destroy
Vcl.Graphics.TCanvasDestroy
System.TObject.Free
此外,Delphi 将我置于 TObbject.Free 方法中的 System.pas 单元中的“Destroy”行。
procedure TObject.Free;
begin
if Self <> nil then
{$IFDEF AUTOREFCOUNT}
__ObjRelease;
{$ELSE}
Destroy;
{$ENDIF}
end;
此时 Self 的值仅显示为 ()。
但是为什么只有当我将一些数据存储到我的多维数组中时才会发生这种 AV。
我可以在运行时创建和设置多维数组的大小,一切都很好。但是,一旦我更改了这个多维数组中某些项目的数据,我就会在关闭我的应用程序时得到 AV。
这是我的完整源代码:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
TSubImage = record
LeftBound: Integer;
RightBound: Integer;
TopBound: Integer;
BottomBound: Integer;
end;
TForm2 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
Image1: TImage;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
SubImages: Array of TSubImage;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
var X,Y,I: Integer;
RegionMask: Array of Array of Integer;
begin
SetLength(RegionMask,Image1.Width+1,Image1.Height+1);
for Y := 0 to Image1.Height do
begin
for X := 0 to Image1.Width do
begin
if Image1.Canvas.Pixels[X,Y] <> clFuchsia then
begin
//Check left pixel
if X > 0 then
begin
if RegionMask[X-1,Y] <> 0 then
begin
RegionMask[X,Y] := RegionMask[X-1,Y];
//Check to se if pixel X position is leftwards to subimages left bound
if Subimages[RegionMask[X,Y]].LeftBound > X then
//Move subimage left bound to match pixel X position
Subimages[RegionMask[X,Y]].LeftBound := X;
//Check to se if pixel X position is rightwards to subimages right bound
if Subimages[RegionMask[X,Y]].RightBound < X then
//Move subimage right bound to match pixel X position
Subimages[RegionMask[X,Y]].RightBound := X;
//Check to se if pixel Y position is upwards to subimages top bound
if Subimages[RegionMask[X,Y]].TopBound > Y then
//Move subimage top bound to match pixel Y position
Subimages[RegionMask[X,Y]].TopBound := Y;
//Check to se if pixel Y position is downwards to subimages bottom bound
if Subimages[RegionMask[X,Y]].BottomBound < Y then
//Move subimage bottom bound to match pixel Y position
Subimages[RegionMask[X,Y]].BottomBound := Y;
end;
end;
//Check top pixel
if Y > 0 then
begin
if RegionMask[X,Y-1] <> 0 then
begin
RegionMask[X,Y] := RegionMask[X,Y-1];
//Check to se if pixel X position is leftwards to subimages left bound
if Subimages[RegionMask[X,Y]].LeftBound > X then
//Move subimage left bound to match pixel X position
Subimages[RegionMask[X,Y]].LeftBound := X;
//Check to se if pixel X position is rightwards to subimages right bound
if Subimages[RegionMask[X,Y]].RightBound < X then
//Move subimage right bound to match pixel X position
Subimages[RegionMask[X,Y]].RightBound := X;
//Check to se if pixel Y position is upwards to subimages top bound
if Subimages[RegionMask[X,Y]].TopBound > Y then
//Move subimage top bound to match pixel Y position
Subimages[RegionMask[X,Y]].TopBound := Y;
//Check to se if pixel Y position is downwards to subimages bottom bound
if Subimages[RegionMask[X,Y]].BottomBound < Y then
//Move subimage bottom bound to match pixel Y position
Subimages[RegionMask[X,Y]].BottomBound := Y;
end;
end;
//Create new region
if RegionMask[X,Y] = 0 then
begin
SetLength(SubImages,Length(SubImages)+1);
//If I comment out this line no exception is raised on closing the from
RegionMask[X,Y] := Length(SubImages);
//Set subimage initial bounds which are coordinates of one pixel
//since we created new region for this pixel
SubImages[RegionMask[X,Y]].LeftBound := X;
SubImages[RegionMask[X,Y]].RightBound := X;
SubImages[RegionMask[X,Y]].TopBound := Y;
SubImages[RegionMask[X,Y]].BottomBound := Y;
end;
end;
end;
end;
Form2.Caption := IntToStr(Length(SubImages)-1);
for I := 0 to Length(Subimages)-1 do
begin
ListBox1.Items.Add(IntToStr(SubImages[I].LeftBound)+','+
IntToStr(SubImages[I].RightBound)+','+
IntToStr(SubImages[I].TopBound)+','+
IntToStr(SubImages[I].BottomBound));
end;
SetLength(RegionMask,0,0);
RegionMask := nil;
end;
end.
【问题讨论】:
-
for Y := 0 to Image1.Height看起来很奇怪。当然for Y := 0 to Image1.Height-1。 X 循环也是如此。另外,为什么要使用 GUI 控件进行操作?当然,您需要的是位图。 -
另外,我猜你正在运行范围检查?
-
是的,这是我的代码中的一个错误,但它对我得到的 AV 没有任何影响。为什么我使用 GUI?这是我不关心速度而只关心结果的第一个实现。最后,我打算使用 TBtimap 和 ScanLine 而不是通过 Canvas.Pixel[X,Y] 方法访问单独的像素。但现在?我想知道为什么会发生这个错误,为什么只有当我将一些数据存储到我的动态多维数组中时,它与 TImage 没有任何关系,除了我最初将它的大小设置为图像尺寸。
-
不,我之前没有启用范围检查(我认为它是默认启用的)。启用范围检查在我的代码中显示了许多错误。实际上,当我一直在引用子图像时,我总是偏离了一项。所以修复这些错误似乎解决了我的 AV 问题,但老实说我不知道如何。
-
始终使用范围检查进行调试
标签: delphi multidimensional-array dynamic-arrays delphi-xe3