模块“GUI.exe"中地址 00822135 处的访问冲突.读取地址 00000040 [英] Access violation at address 00822135 in module 'GUI.exe'.Read of address 00000040

查看:143
本文介绍了模块“GUI.exe"中地址 00822135 处的访问冲突.读取地址 00000040的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

sqlite 有一个数据库——一个描述符,包含表列表、域列表、字段列表、限制列表(主键和外键)、索引列表.我是从 Delphi XE3 的内置组件的帮助下连接到这个基础的.有一个单独的模块,其中描述了类 TTableSpec、TFieldSpec、TConstraintSpec、TConstraintDetSpec 和 TDomainSpec.这些类对应于上述基础sqlite的记录.在 TTableSpec 类中有这样的 FFields 字段: TComponent 成为像 TFieldSpec 这样的对象的所有者,这些对象也已经从基础卸载(例如,DBSchema 也包含作为所有表的所有者的 FTables 字段),并且在类 TFieldSpec 中有一个 FDomainSpec 字段:TDomainSpec.实际上我给出了一个与错误相关的类代码

There is sqlite a database - a descriptor, containing the list of tables, the list of domains, the list of fields, the list of restrictions (primary and foreign keys), the list of indexes. I am connected from Delphi XE3 with the help of the built-in component to this basis. There is a separate module in which the classes TTableSpec, TFieldSpec, TConstraintSpec, TConstraintDetSpec, TDomainSpec are described. These classes correspond to records of above-mentioned sqlite of basis. In TTableSpec classes there are such FFields fields: TComponent which becomes the owner of objects like TFieldSpec which have been also unloaded from basis (for example, also DBSchema contains the FTables field being the owner of all tables), and in the class TFieldSpec there is a FDomainSpec field: TDomainSpec. Actually I give a code of classes connected to an error

type
TDataTypeId = (DataTypeId_String, DataTypeId_SmallInt, DataTypeId_Integer, DataTypeId_Word,
               DataTypeId_Boolean, DataTypeId_Float, DataTypeId_Currency,
               DataTypeId_BCD, DataTypeId_FmtBCD, DataTypeId_Date,
               DataTypeId_Time, DataTypeId_DateTime, DataTypeId_TimeStamp,
               DataTypeId_Bytes, DataTypeId_VarBytes, DataTypeId_Blob,
               DataTypeId_Memo, DataTypeId_Graphic, DataTypeId_fmtMemo,
               DataTypeId_FixedChar, DataTypeId_WideChar, DataTypeId_LargeInt,
               DataTypeId_Array, DataTypeId_FixedWideChar, DataTypeId_WideMemo, DataTypeId_Default);
TDBSchemaSpec=class(Tcomponent)
  private
    FDomains: TComponent;
    FTables : TComponent;
  public
    procedure Setup();
    destructor Destroy; override;
    property Domains: TComponent read FDomains;
    property Tables : TComponent read FTables;
end;
TDomainSpec = class(TComponent)
  private
    FName: string;
    FDescription: String;
    FDataTypeId: TDataTypeId;
    FLength: Cardinal;
    FCharLength: Cardinal;
    FPrecision: Cardinal;
    FScale: Cardinal;
    FWidth: Word;
    FAlign: TAlignSpec;
    FShowNull: Boolean;
    FShowLeadNulls: Boolean;
    FThousandsSeparator: Boolean;
  public
    procedure Setup(FName: string; FDescription: String; FDataTypeId: TDataTypeId;
    FLength: Cardinal;FCharLength: Cardinal;FPrecision: Cardinal;FScale: Cardinal;
    FWidth: Word;FAlign: TAlignSpec;FShowNull: Boolean;FShowLeadNulls: Boolean;
    FThousandsSeparator: Boolean);
    destructor Destroy; override;
    property Name: String read FName;
    property Description: String read FDescription;
    property DataTypeId: TDataTypeId read FDataTypeId;
    property Length: Cardinal read FLength;
    property CharLength: Cardinal read FCharLength;
    property Precision: Cardinal read FPrecision;
    property Scale: Cardinal read FScale;
    property Width: Word read FWidth;
    property Align: TAlignSpec read FAlign;
    property ShowNull: Boolean read FShowNull;
    property ShowLeadNulls: Boolean read FShowLeadNulls;
    property ThousandsSeparator: Boolean read FThousandsSeparator;
  end;

TTableSpec= class(TComponent)
  private
    FFields : TComponent;
    FIndices: TComponent;
    FConstraints : TComponent;
    FName : string;
    FDescription: string;
    FCanAdd:  boolean;
    FCanEdit: boolean;
    FCanDelete: boolean;
  public
    procedure Setup(FName : string; FDescription:string;
    FCanAdd:  boolean; FCanEdit: boolean; FCanDelete: boolean);
    destructor Destroy; override;
    property Description : string read FDescription;
    property Name : string read FName;
    property CanAdd:  boolean read FCanAdd;
    property CanEdit: boolean read FCanEdit;
    property CanDelete: boolean read FCanDelete;
    property Fields : TComponent read FFields;
    property Indices: TComponent read FIndices;
    property Constraints : TComponent read FConstraints;
  end;

TFieldSpec = class(TComponent)
  private
    FDomainSpec: TDomainSpec;
    FPosition: integer;
    FFieldName: string;
    FDescription: string;
    FCanInput: boolean;
    FCanEdit: boolean;
    FShowInGrid: boolean;
    FShowInDetails: boolean;
    FIsMean: boolean;
    FAutoCalculated: boolean;
    FRequired: boolean;
  public
    procedure Setup(FDomainSpec: TDomainSpec; FPosition: integer; FFieldName: string; FDescription: string; FCanInput: boolean; FCanEdit: boolean;
    FShowInGrid: boolean; FShowInDetails: boolean; FIsMean: boolean;FAutoCalculated: boolean;
    FRequired: boolean);
    destructor Destroy; override;
    property DomainSpec: TDomainSpec read FDomainSpec;
    property Position: integer read FPosition;
    property FieldName: string read FFieldName;
    property Description: string read FDescription;
    property CanInput: boolean read FCanInput;
    property CanEdit: boolean read FCanEdit;
    property ShowInGrid: boolean read FShowInGrid;
    property ShowInDetails: boolean read FShowInDetails;
    property IsMean: boolean read FIsMean;
    property AutoCalculated: boolean read FAutoCalculated;
    property Required: boolean read FRequired;
 end;

在应用程序中有一个表单 fmListOfTables,从其中在 CheckListBox 中选择了数据将在其他窗口的 DBGrid 中显示的表名.错误

In application there is a form fmListOfTables from which in CheckListBox the table name which data will be displayed in DBGrid in other window is selected. Error

Access violation at address 00822135 in module 'GUI.exe'.Read of address 00000040.(When debugging Project GUI.exe raised exception class $C0000005 with message 'access violation at 0x00822135:  read of address 0x00000040'.  )  

出现在行

if ((TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i] is TFieldSpec) and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec).DataTypeId<>DataTypeId_Blob) and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec).DataTypeId<>DataTypeId_WideMemo)) then

在选择表格的过程中

procedure TfmListOfTables.ListBox1DblClick(Sender: TObject);
var  fmShowData : TfmTableData;
      i : integer;
      querystr : string;
begin
  MainWindow.IBDatabase1.DatabaseName:=MainWindow.dbname;
  MainWindow.IBDatabase1.Connected:=true;
  fmShowData:=TfmTableData.Create(MainWindow);
  fmShowData.Caption:=ListBox1.Items.Strings[ListBox1.ItemIndex];
  fmShowData.tname:=ListBox1.Items.Strings[ListBox1.ItemIndex];
  DisplayTable:=ListBox1.Items.Strings[ListBox1.ItemIndex];
  querystr:='select ';
  for i:= 0 to TTableSpec(DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.ComponentCount-1 do
     begin
     if ((TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i] is TFieldSpec) and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec).DataTypeId<>DataTypeId_Blob) and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec).DataTypeId<>DataTypeId_WideMemo)) then
        querystr:=querystr+TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).FieldName+', ';
     end;
  Delete(querystr, Length(querystr)-1, 1);
  querystr:=querystr+'from '+fmShowData.tname;
  fmShowData.IBQuery1.SQL.Clear;
  fmShowData.IBQuery1.SQL.Add(querystr);
  fmShowData.IBQuery1.Open;
  fmShowData.DBGrid1.DataSource:=fmShowData.DataSource1;
  for I := 0 to fmShowData.DBGrid1.Columns.Count-1 do
    fmShowData.DBGrid1.Columns[i].Width:=90;
  fmShowData.DragKind:=dkDock;
  fmShowData.DragMode:=dmAutomatic;
  fmShowData.tname:=ListBox1.Items.Strings[ListBox1.ItemIndex];
  TfmTableData(fmShowData).databasetable:=ListBox1.Items.Strings[ListBox1.ItemIndex];
  fmShowData.Show;
end;

推荐答案

我们来看看导致问题的那行代码:

Let's look at the line of code that causes the problems:

if ((TTableSpec(MainForm.DBSchema.Tables.FindComponent(
  ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i] is TFieldSpec) 
  and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.DBSchema.Tables.FindComponent(
  ListBox1.Items.Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec)
  .DataTypeId<>DataTypeId_Blob) and (TDomainSpec(TFieldSpec(TTableSpec(MainForm.
  DBSchema.Tables.FindComponent(ListBox1.Items.
  Strings[ListBox1.ItemIndex])).Fields.Components[i]).DomainSpec).
  DataTypeId<>DataTypeId_WideMemo)) then

很难找到有关该行代码的任何信息.纯粹而简单,这是一种彻头彻尾的讽刺.

It's very hard to find anything to say about that line of code. Pure and simple it is an outright travesty.

首先要做的是使用一些局部变量.例如:

The very first thing to do is to use some local variables. For example:

ComponentName := ListBox1.Items.Strings[ListBox1.ItemIndex];

然后我们可以这样写:

Component1 := MainForm.DBSchema.Tables.FindComponent(ComponentName);

我们继续本着这种精神:

Continuing in this vein we have:

Component2 := TTableSpec(Component1).Fields.Components[i];

那么代码可以是这样的:

Then the code can look like this:

if (Component2 is TFieldSpec) 
and (TDomainSpec(TFieldSpec(Component2).DomainSpec).DataTypeId<>DataTypeId_Blob) 
and (TDomainSpec(TFieldSpec(Component2).DomainSpec).DataTypeId<>DataTypeId_WideMemo)) then

您的首要任务是按照我建议的方式以理智的方式重新编写代码.

Your first task is to re-write the code in a sane manner along the lines I suggest.

然后是实际的错误.您在读取地址 $00000040 时存在访问冲突.这是尝试取消引用空指针的标志.很明显,这里的内容是 nil.我不能说.但是您的调试器会告诉您.确保将其配置为在引发异常时中断.这是 IDE 调试器选项中的设置.

Then there is the actual error. You have an access violation with a read of address $00000040. That is the hallmark of an attempt to de-reference the null pointer. Clearly something in here is nil. I can't tell that. But your debugger will tell you that. Make sure you configure it to break when exceptions are raised. That's a setting in the IDE debugger options.

很可能 FindComponent 调用之一返回 nil.或者DomainSpecnil.您可能需要将单个 if 语句分解为多个 if 语句,以便于调试.

Quite possibly one of the FindComponent calls returns nil. Or perhaps DomainSpec is nil. You may need to break that single if statement into multiple if statements to make it easier to debug.

我的最后一点是重申我最初的建议.这段代码是行不通的.立即将其重构为合理的形式.

My final point is to re-iterate my initial advice. This code is unworkable. Re-factor it into a sane form immediately.

这篇关于模块“GUI.exe"中地址 00822135 处的访问冲突.读取地址 00000040的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆