Arrays 组合框上的访问冲突清除

Arrays 组合框上的访问冲突清除,arrays,delphi,combobox,delphi-xe8,Arrays,Delphi,Combobox,Delphi Xe8,我正在使用DelphiXe8编写一个可以访问多个数据库的客户机/服务器应用程序 作为设置表单的一部分,TCOMBOXEX用于显示动态记录数组并从中进行选择,动态记录数组保存每个数据库的信息,两个按钮用于从数组中添加或删除记录 数组保存并加载到单个格式化字符串中,每个记录的name属性用作每个组合框项的标题 在form show和add或remove database(添加或删除数据库)按钮上,会调用一个更新过程,该过程首先清除并重新加载数组,然后重新填充组合框 procedure TSettin

我正在使用DelphiXe8编写一个可以访问多个数据库的客户机/服务器应用程序

作为设置表单的一部分,TCOMBOXEX用于显示动态记录数组并从中进行选择,动态记录数组保存每个数据库的信息,两个按钮用于从数组中添加或删除记录

数组保存并加载到单个格式化字符串中,每个记录的name属性用作每个组合框项的标题

在form show和add或remove database(添加或删除数据库)按钮上,会调用一个更新过程,该过程首先清除并重新加载数组,然后重新填充组合框

procedure TSettingsForm.UpdateDatabaseCombo;
var
  i: integer;
begin
  LoadDatabaseList; // Clears and reloads databaselist dynamic array.

  with dbCombo.Items do
  begin
    BeginUpdate;
    if Length(DatabaseList) <> 0 then
    begin
      Clear;    // This section works fine.
      for i := 0 to High(DatabaseList) do
      begin
        Add(DatabaseList[i].dbName);
        dbCombo.ItemsEx[i].ImageIndex := 17;
      end;
    end;

    if (Length(DatabaseList) < 1) and (Count <> 0) then
    begin
      Clear;  // Access violation on this line.
    end;
    EndUpdate;
  end;
end;
这将再次从组合框中清除最后一项,没有例外,但文本仍然保留

请任何人帮我解决这个问题,也许能指出我所缺少的简单的小东西


添加……。

根据要求,以下是
UpdateDatabaseCombo
例程的更新代码

procedure TSettingsForm.UpdateDatabaseCombo;
var
  i: integer;
begin
  LoadDatabaseList; // Clears and reloads databaselist dynamic array.

  if dbCombo.Items.Count <> 0 then
    dbCombo.Items.Clear;

  with dbCombo.Items do
  begin
    BeginUpdate;
    if Length(DatabaseList) <> 0 then
    begin
      for i := 0 to High(DatabaseList) do
      begin
        Add(DatabaseList[i].dbName);
        dbCombo.ItemsEx[i].ImageIndex := 17;
      end;
    end;
    EndUpdate;
  end;
end;

当组合框为空时,如果调用了
clear
,则程序中的任何位置都会发生异常。

非常感谢大家的帮助。我终于找到了问题所在

“天啊,我觉得自己好傻”

罪魁祸首是在
OnChange
事件处理程序中,我在其中放置了一条指令,以从databases record password属性填充编辑框,当从combobox中选择数据库时,该属性将自动更改

procedure TSettingsForm.UpdateDatabaseCombo;
var
  i: integer;
begin
  LoadDatabaseList; // Clears and reloads databaselist dynamic array.

  with dbCombo.Items do
  begin
    BeginUpdate;
    if Length(DatabaseList) <> 0 then
    begin
      Clear;    // This section works fine.
      for i := 0 to High(DatabaseList) do
      begin
        Add(DatabaseList[i].dbName);
        dbCombo.ItemsEx[i].ImageIndex := 17;
      end;
    end;

    if (Length(DatabaseList) < 1) and (Count <> 0) then
    begin
      Clear;  // Access violation on this line.
    end;
    EndUpdate;
  end;
end;
问题是,我没有添加条件语句来检查数据库列表中是否有要从中加载的项,因此在没有引发异常时

两天浪费在一个简单的
if
语句上。我已经有几年没有做任何真正的编程了,我真的很怀念那些让人毛骨悚然的时刻


再次感谢

去掉
with
语句,对每个属性使用
dbCombo.Items
,然后使用调试器找出错误所在。这是在代码中使用
with
时可能发生的另一个坏事情示例。这使得问题很难发现,调试也不可能(至少在您做正确的事情并取消使用
with
)之前)。感谢@Ken的回复,但在这种情况下,您是错的,因为问题不在于
with
循环,为了证明这一点,我删除了第二条
if
语句,替换为
if dbCombo.Items.Count 0,然后在加载数组后立即清除dbCombo.Items,但结果仍然是相同的异常错误。ps对于上次的评论表示抱歉,错误地按了enter。@KenWhite没有错:无论如何,您应该避免使用“with”。不管怎样,我怀疑你的问题在于你没有给我们看的东西。调用dbCombo.Items.Clear两次不应导致AV。请将用于从数据库列表中添加和删除记录的代码添加到您的q中。@Ken,请原谅,我并不是说您对
的使用是错误的,我只是说在这种情况下,这不是问题的原因,无论如何,我现在已经更新了问题以提供更多信息。我认为您应该尝试在配置中启用“使用调试dcu”。然后跑。然后使用调用堆栈确定调用combobox clear时异常发生的确切位置。
procedure TSettingsForm.DBRemoveButtonClick(Sender: TObject);
var
  ALength: Cardinal;
  i: Cardinal;
begin
  ALength := Length(DatabaseList);
  Assert(ALength > 0);
  Assert(dbCombo.ItemIndex < ALength);
  for i := dbCombo.ItemIndex + 1 to ALength - 1 do
    DatabaseList[i - 1] := DatabaseList[i];
  SetLength(DatabaseList, ALength - 1);
  SaveDatabaseList;
  UpdateDatabaseCombo; 
  if dbCombo.Items.Count <> 0 then
    dbCombo.ItemIndex := 0;
end;