【问题标题】:Dynamic array variable is not showing in Local Variables debug window动态数组变量未显示在局部变量调试窗口中
【发布时间】:2014-01-18 01:43:35
【问题描述】:

我有一些我以前从未见过的东西。调试时未出现在“局部变量”窗口中的局部变量。我正在附上一张图片。

如您所见,我在代码中使用了该变量,并且在调试时禁用了优化。但我也在使用泛型和匿名方法,我不是专家。 有问题的程序的代码是这样的(该程序的作用是按第一个数组中字符串的长度以 desc 顺序对前两个数组 ArrayNomes、ArrayValores 进行排序):

  procedure OrdenarArrays(var ArrayNomes, ArrayValores: array of string; var ArrayIndices: array of Integer);
  var
    Comparer: IComparer<Integer>;
    I: Integer;
    tmpNomesCampos, tmpValoresCampos: array of String;
  begin

    SetLength(tmpNomesCampos,   cdsCadastro.FieldCount);
    SetLength(tmpValoresCampos, cdsCadastro.FieldCount);

    //Carregar os NomesCampos para serem usados na comparação
    for I := 0 to High(arrayIndices) do
    begin
      tmpNomesCampos[I] := ArrayNomes[I];
    end;

    { Cria novo delegatedcomparer. Ele permite o uso de um callback para comparar os arrays}
    Comparer := TDelegatedComparer<Integer>.Create(
      { TComparison<Integer> }
      function(const Left, Right: Integer): Integer
      begin
        {colocar em ordem decrescente de acordo com o tamanho do nome do campo}
//        Result := Left - Right;
        Result := -(Length(tmpNomesCampos[Left]) - Length(tmpNomesCampos[Right]));
      end);

    { Ordena o Array base }
    TArray.Sort<Integer>(arrayIndices, Comparer);

    //Reordenar os NomesCampos de acordo com o array IndicesCampos
    for I := 0 to High(arrayIndices) do
    begin
      tmpNomesCampos[I]   := ArrayNomes[arrayIndices[I]];
      tmpValoresCampos[I] := ArrayValores[arrayIndices[I]];
    end;

    //Salvar nos arrays definitivos;
    for I := 0 to High(arrayIndices) do
    begin
      ArrayNomes[I]   := tmpNomesCampos[I];
      ArrayValores[I] := tmpValoresCampos[I];
    end;

  end;

这个变量没有显示错误吗?它是一个已知的错误吗?或者它可能是使用我不知道的泛型和匿名方法的一个特性?

系统:Windows 7 64 位/Delphi XE(最新更新)


更新:将代码更改为下面的简化控制台版本。这可能会帮助任何想要在他的 Delphi 版本中进行测试的人。 注意:它不会填充原始数组,因为没有必要显示问题;

program Project1;


{$APPTYPE CONSOLE}

uses
  SysUtils, Generics.Collections, Generics.Defaults;

  procedure OrdenarArrays(var ArrayNomes, ArrayValores: array of string; var ArrayIndices: array of Integer);
  var
    Comparer: IComparer<Integer>;
    I: Integer;
    tmpNomesCampos, tmpValoresCampos: array of String;
  begin

    SetLength(tmpNomesCampos,   Length(arrayIndices));
    SetLength(tmpValoresCampos, Length(arrayIndices));

    //Carregar os NomesCampos para serem usados na comparação
    for I := 0 to High(arrayIndices) do
    begin
      tmpNomesCampos[I] := ArrayNomes[I];
    end;

    { Cria novo delegatedcomparer. Ele permite o uso de um callback para comparar os arrays}
    Comparer := TDelegatedComparer<Integer>.Create(
      { TComparison<Integer> }
      function(const Left, Right: Integer): Integer
      begin
        {colocar em ordem decrescente de acordo com o tamanho do nome do campo}
  //        Result := Left - Right;
        Result := -(Length(tmpNomesCampos[Left]) - Length(tmpNomesCampos[Right]));
      end);

    { Ordena o Array base }
    TArray.Sort<Integer>(arrayIndices, Comparer);

    //Reordenar os NomesCampos de acordo com o array IndicesCampos
    for I := 0 to High(arrayIndices) do
    begin
      tmpNomesCampos[I]   := ArrayNomes[arrayIndices[I]];
      tmpValoresCampos[I] := ArrayValores[arrayIndices[I]];
    end;

    //Salvar nos arrays definitivos;
    for I := 0 to High(arrayIndices) do
    begin
      ArrayNomes[I]   := tmpNomesCampos[I];
      ArrayValores[I] := tmpValoresCampos[I];
    end;

  end;

var
  NomesCampos, ValoresCampos: array of String;
  IndicesCampos: array of Integer;
  I: Integer;
begin
  try

    SetLength(NomesCampos,   42);
    SetLength(ValoresCampos, 42);
    SetLength(IndicesCampos, 42);

//    for I := 0 to 41 do

    OrdenarArrays(NomesCampos, ValoresCampos, IndicesCampos);

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

【问题讨论】:

  • 首先我会摆脱对 cdsCadastro.FieldCount 的依赖并将其传递给方法。如果仅此一项没有帮助,您可以将该方法从本地嵌套方法中移出。
  • 你能不能做三行,其中第一行和第三行会用到,然后看第二行是否可见。或者在禁用优化的情况下编译程序(推荐用于调试)。它会显示在第 2 行,在使用数组的行之间吗?
  • @Arioch'优化已被禁用。我不好,我会更新问题。
  • 您无能为力。这似乎是一个错误。得到一个以后的德尔福。你有四个版本过时了。
  • @DavidHeffernan 你的意思是让他将已知的错误交换为未知的? :-)

标签: delphi debugging delphi-xe


【解决方案1】:

这是 XE5 中仍然存在的调试器/IDE 错误。正如您所怀疑的,问题与匿名方法的使用有关。关键是变量是否被捕获。捕获变量时,该变量不会显示在 Locals 窗口中。这是我能编出的最短的 SSCCE:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

procedure Foo1;
var
  func: TFunc<Integer>;
  val: Integer;
begin
  val := 666;
  func :=
    function: Integer
    begin
      Result := val;
    end;
end;

procedure Foo2;
var
  func: TFunc<Integer>;
  val: Integer;
begin
  val := 666;
  func :=
    function: Integer
    begin
      Result := 666;
    end;
end;

begin
  Foo1;
  Foo2;
  Readln;
end.

在调试器中,Foo1.val 不会显示在 Locals 窗口中。但是Foo2.val 可以。

QC#121821

【讨论】:

  • 另外,您不能为Foo1.val添加手表
  • @LURD 涉及更多与 QC 的斗争,他们是否注意到?我很震惊他们还没有修复浮点控制.....
  • 它仍然存在于 XE7 和 XE8 中。至少有解决方法吗?我唯一能想到的就是引入额外的本地变量指针并检查它们。
  • 注意 - RAD Studio 11 中仍然存在问题
【解决方案2】:

不是问题的答案,而是关于如何以更简单的方式编写例程的建议(至少如果我理解它应该做什么)

procedure OrderArrays(var ArrayNameValuePairs: array of TPair<string, string>);
begin
  TArray.Sort<TPair<string, string>>(ArrayNameValuePairs,
    TComparer<TPair<string, string>>.Construct(
      function(const Left, Right: TPair<string, string>): Integer
      begin
        Result := Length(Right.Key) - Length(Left.Key);
      end));
end;

如您所见,我将名称和值组合在一起,因为它们显然属于同一类。这使得对这个组合数组的排序变得更加容易,因为您不必对包含 indizes 的第三个数组进行排序来重新排序两个原始数组。

【讨论】:

  • 谢谢。我稍后会试试这个。使用第三个数组的好处是我什至不需要对前两个数组进行排序,即使这样做,我也可以知道更改前的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-13
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
相关资源
最近更新 更多