2

我有一个 Delphi 7.0 应用程序,每次它从与组合框关联的字符串列表中写入一个空字符串时,它都会抛出一个内存访问异常/消息框:

csvstrlst := combobox1.Items;

csvstrlst.clear;
csvstrlst.add('');    //problem
csvstrlst.add('a');   //no problem
csvstrlst.add('');    //problem
csvstrlst.add('b');   //no problem

//throws memory access messages (I think the writeln writes a line though)
for n := 1 to csvstrlst.Count do begin
    writeln(out_file,csvstrlst.strings[n-1])
end;

//throws memory access messages (writeln does write a comma text string though)
writeln(out_file,csvstrlst.commatext);

在 Windows 7 或 XP 上运行。作为应用程序或在 D7 IDE 中。如果更改其所在窗体的父级,则具有空字符串项的组合框也会导致相同的错误。

有没有其他人见过或听说过这个问题?还有其他可用的信息吗?

4

2 回答 2

3

这是 QC 中描述的已知且已解决的错误:

从下拉列表中选择空项目时,TCombobox 提供 AV


尽管这是一个错误,但您不应重用控件中的部件来执行问题中描述的某些数据任务。

这样做不会保存任何东西,但会得到大部分时间不需要的副作用(控件被重新绘制和/或触发事件)

如果你想要一个TStringList然后创建一个实例。

csvstrlst := TStringList.Create;
try

  // csvstrlst.Clear;
  csvstrlst.Add( '' );
  csvstrlst.Add( 'a' );
  csvstrlst.Add( '' );
  csvstrlst.Add( 'b' );

  for n := 0 to csvstrlst.Count - 1 do 
  begin
    WriteLn( out_file, csvstrlst[n] )
  end;

  WriteLn( out_file, csvstrlst.CommaText );

finally
  csvstrlst.Free;
end;
于 2013-07-18T07:02:47.173 回答
2

正如 Rufo 爵士发现的那样,该问题是 Delphi 7 中引入的 VCL 错误,如QC#2246中所述。根据该报告,该错误已在主要版本号 7 的构建中得到解决,因此您可以通过应用最新的 Delphi 7 更新来解决该问题。

如果没有,那么您可以从外部解决问题。我实际上没有安装 Delphi 7 来测试它,但我相信这个插入器类会起作用。

type
  TFixedComboBoxStrings = class(TComboBoxStrings)
  protected
    function Get(Index: Integer): string; override;
  end;

  TComboBox = class(StdCtrls.TComboBox)
  protected
    function GetItemsClass: TCustomComboBoxStringsClass; override;
  end;

function TFixedComboBoxStrings.Get(Index: Integer): string;
var
  Len: Integer;
begin
  Len := SendMessage(ComboBox.Handle, CB_GETLBTEXTLEN, Index, 0);
  if (Len <> CB_ERR) and (Len > 0) then
  begin
    SetLength(Result, Len);
    SendMessage(ComboBox.Handle, CB_GETLBTEXT, Index, Longint(PChar(Result)));
  end
  else
    SetLength(Result, 0);
end;

function TComboBox.GetItemsClass: TCustomComboBoxStringsClass;
begin
  Result := TFixedComboBoxStrings;
end;

Delphi 7 中引入的错误只是if语句如下:

if Len <> CB_ERR then

因此,当Len为零时,即当项目为空字符串时,将选择 的True分支if。然后,SendMessage变成:

SendMessage(ComboBox.Handle, CB_GETLBTEXT, Index, Longint(PChar('')));

现在,PChar('')经过特殊处理并计算为指向包含零字符的只读内存的指针。因此,当组合框窗口过程尝试写入该内存时,会发生访问冲突,因为该内存是只读的。

于 2013-07-18T08:24:59.827 回答