Access violation at address 00822135 in module 'GUI.exe'.Read of address 00000040 [closed]

做~自己de王妃 提交于 2019-12-12 06:55:38

问题


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;

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'.  )  

arises at line

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

in procedure of a choice of the table

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;

回答1:


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];

Then we can write this:

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.

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.

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.



来源:https://stackoverflow.com/questions/14030815/access-violation-at-address-00822135-in-module-gui-exe-read-of-address-0000004

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!