简体   繁体   中英

Delphi: getting access violation error at run-time

I'm pretty new to Delphi and am attempting to use different units to store TLists and TObjects, as well as generate other combobox options based on previous combobox selections. I am receiving the following error messages immediately after running:

Project Project1.exe raised exception class $C0000005 with message 'access violation at 0x004087d7: read of address 0x00000000

Access violation at address 00408813 in module 'Project1.exe'. Read of address 00000000.

I've traced through the steps in the debugging tool but I can't see why it won't work. I have googled the issue and have found a few solutions but nothing that seems like it applies to my current problem.

unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TfMain = class(TForm)
    lCPU: TLabel;
    cbCPU: TComboBox;
    lGPU: TLabel;
    cbGPU: TComboBox;
    lMotherboard: TLabel;
    cbMotherboard: TComboBox;
    lRAM: TLabel;
    cbRAM: TComboBox;
    eCompatible: TEdit;
    lCompatible: TLabel;
    eCost: TEdit;
    lCost: TLabel;
    Label11: TLabel;
    lbCPU: TListBox;
    lbMotherboard: TListBox;
    lbGPU: TListBox;
    lbRAM: TListBox;
    procedure FormShow(Sender: TObject);
    procedure cbCPUChange(Sender: TObject);
  private
    { Private declarations }
  public
//    procedure cbCPUpopulate();
  end;

  type TGPU = class(TObject)
    public
      name : string;
      vram : integer;
      clock : integer;
      price : string;
  end;

  type TCPU = class(TObject)
    public
      name : string;
      cores : integer;
      clock : real;
      intel : boolean;
      amd : boolean;
      price : string;
  end;

  type TMobo = class(TObject)
    public
      name : string;
      intel : boolean;
      amd : boolean;
      price : string;
  end;

  type TRAM = class(TObject)
    public
      name : string;
      memory : integer;
      clock : integer;
      price : string;
  end;

var
  fMain: TfMain;

implementation

{$R *.dfm}

uses CPUs, GPUs, Motherboards;

procedure TfMain.cbCPUChange(Sender: TObject);
var
i : integer;
mobo : TMobo;
begin
  if TCPU(fMain.cbCPU.ItemIndex).intel = true then begin
    for i := 0 to Motherboards.MoboPartsList.Count-1 do begin
      mobo := TMobo(Motherboards.MoboPartsList.Items[i]);
      if mobo.intel = true then begin
        fMain.cbMotherboard.Items.AddObject(mobo.name, mobo);
      end;
    end;
  end;
end;

procedure cbCPUpopulate();
var
i : integer;
CPU : TCPU;
begin
  for i := 0 to CPUs.CPUPartsList.Count-1 do begin
    CPU := TCPU(CPUs.CPUPartsList.Items[i]);
    fMain.cbCPU.Items.AddObject(CPU.name, CPU);
  end;
end;

procedure TfMain.FormShow(Sender: TObject);
begin
  Motherboards.MakeMoboList;
  CPUs.MakeCPUList();
  GPUs.popgpulist();
  cbCPUpopulate;
end;

end.

In cbCPUChange() , you are accessing the TCPU objects incorrectly.

The expression TCPU(fMain.cbCPU.ItemIndex) is type-casting a list index into an object pointer . You need to instead use the ItemIndex to access the ComboBox's Objects[] property, which is filled with TCPU objects by cbCPUpopulate() .

Also, there is no need to use the fMain global variable from inside a method of the TfMain class. Use the method's implicit Self pointer instead.

Try something more like this:

procedure TfMain.cbCPUChange(Sender: TObject);
var
  i : integer;
  mobo : TMobo;
begin
  cbMotherboard.Items.BeginUpdate;
  try
    cbMotherboard.Items.Clear;
    i := cbCPU.ItemIndex;
    if i < 0 then Exit;
    if TCPU(cbCPU.Items.Objects[i]).intel then begin
      for i := 0 to Motherboards.MoboPartsList.Count-1 do begin
        mobo := TMobo(Motherboards.MoboPartsList.Items[i]);
        if mobo.intel then begin
          cbMotherboard.Items.AddObject(mobo.name, mobo);
        end;
      end;
    end;
  finally
    cbMotherboard.Items.EndUpdate;
  end;
end;

On a side note, the declarations of the TCPU , TMobo , and TRAM types do not belong in the MainForm unit. They should be declared in the other units that are actually creating object lists of those types, eg: TCPU in the CPUs unit, TMobo in the Motherboards unit, etc:

unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TfMain = class(TForm)
    lCPU: TLabel;
    cbCPU: TComboBox;
    lGPU: TLabel;
    cbGPU: TComboBox;
    lMotherboard: TLabel;
    cbMotherboard: TComboBox;
    lRAM: TLabel;
    cbRAM: TComboBox;
    eCompatible: TEdit;
    lCompatible: TLabel;
    eCost: TEdit;
    lCost: TLabel;
    Label11: TLabel;
    lbCPU: TListBox;
    lbMotherboard: TListBox;
    lbGPU: TListBox;
    lbRAM: TListBox;
    procedure FormShow(Sender: TObject);
    procedure cbCPUChange(Sender: TObject);
  private
    { Private declarations }
    procedure cbCPUpopulate;
  public
  end;

var
  fMain: TfMain;

implementation

{$R *.dfm}

uses
  CPUs, GPUs, Motherboards;

procedure TfMain.cbCPUChange(Sender: TObject);
var
  i : integer;
  mobo : Motherboards.TMobo;
begin
  cbMotherboard.Items.BeginUpdate;
  try
    cbMotherboard.Items.Clear;
    i := cbCPU.ItemIndex;
    if i < 0 then Exit;
    if CPUs.TCPU(cbCPU.Items.Objects[i]).intel then begin
      for i := 0 to Motherboards.MoboPartsList.Count-1 do begin
        mobo := Motherboards.TMobo(Motherboards.MoboPartsList.Items[i]);
        if mobo.intel then begin
          cbMotherboard.Items.AddObject(mobo.name, mobo);
        end;
      end;
    end;
  finally
    cbMotherboard.Items.EndUpdate;
  end;
end;

procedure TfMain.cbCPUpopulate;
var
  i : integer;
  CPU : CPUs.TCPU;
begin
  for i := 0 to CPUs.CPUPartsList.Count-1 do begin
    CPU := CPUs.TCPU(CPUs.CPUPartsList.Items[i]);
    cbCPU.Items.AddObject(CPU.name, CPU);
  end;
end;

procedure TfMain.FormShow(Sender: TObject);
begin
  Motherboards.MakeMoboList;
  CPUs.MakeCPUList;
  GPUs.popgpulist;
  cbCPUpopulate;
end;

end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM