Delphi / Windows组合框中的空字符串会导致访问异常

时间:2013-07-18 06:34:39

标签: delphi delphi-7

我有一个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中。带有空字符串项的Combobox如果更改了表单的父级,也会导致相同的错误。

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

2 个答案:

答案 0 :(得分:3)

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

TCombobox gives AV when selecting empty item from dropdown


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

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

如果您想拥有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;

答案 1 :(得分:2)

正如Rufo爵士所发现的那样,问题是在QC#2246中描述的Delphi 7中引入的VCL错误。根据该报告,该bug在主版本号为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的{​​{1}}分支。然后,if变为:

SendMessage

现在,SendMessage(ComboBox.Handle, CB_GETLBTEXT, Index, Longint(PChar(''))); 有特殊处理,并评估指向只读包含零字符的内存的指针。因此,当组合框窗口过程尝试写入该内存时,会发生访问冲突,因为内存是只读的。