微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Delphi:在运行时出现访问冲突错误

如何解决Delphi:在运行时出现访问冲突错误

我对Delphi来说还很陌生,我正尝试使用不同的单元来存储TList和TObject,以及根据以前的组合框选择生成其他组合框选项。运行后,我立即收到以下错误消息:

Project Project1.exe引发带有消息的异常类$ C0000005 '在0x004087d7发生访问冲突:读取地址0x00000000

模块'Project1.exe'中地址00408813的访问冲突。阅读 地址00000000。

我已经跟踪了调试工具中的步骤,但是看不到为什么它不起作用。我已经搜索了这个问题,并找到了一些解决方案,但似乎没有什么适用于我当前的问题。

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.

解决方法

cbCPUChange()中,您错误地访问了TCPU对象。

表达式TCPU(fMain.cbCPU.ItemIndex)正在将列表索引类型转换为对象指针。您需要使用ItemIndex来访问ComboBox的Objects[]属性,该属性由TCPUcbCPUpopulate()个对象填充。

此外,也不需要从fMain类的方法内部使用TfMain全局变量。改用该方法的隐式Self指针。

尝试更多类似的方法:

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;

另一方面,TCPUTMoboTRAM类型的声明不属于MainForm单元。应该在实际创建这些类型的对象列表的其他单元中声明它们,例如:TCPU单元中的CPUsTMobo单元中的Motherboards等:

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.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。