【问题标题】:Delphi - EAcessViolation ErrorDelphi - EAcessViolation 错误
【发布时间】:2012-05-28 17:22:17
【问题描述】:

所以伙计们...我已经阅读了很多内容,并且尝试过使用诸如 madExcept 之类的插件(我是新手),但到目前为止我还无法确定是什么导致了我的错误。

在看似随机的时间调用 SetLength() 时,我的代码出现 EAccessViolation 异常。我一直无法确定其背后的原因,我什至无法将其追踪到一行代码。我希望你能帮我解决这个问题。

这个函数应该在一个数字数组中寻找重复的模式并计算它们。 目前,它的逻辑还没有 100% 准备好,但我想在继续之前纠正这些错误。

完成后如何工作的示例:

给定数组 {1, 2, 3, 4, 1, 2, 3, 5},它将子数组 (1, 2, 3) 与所有其他可能的子数组 (4, 1, 2) 进行比较), (1, 2, 3) 和 (2, 3, 5),计算它们相同的情况。然后该函数将进入下一个长度并通过比较 (1, 2, 3, 4) 和 (1, 2, 3, 5) 再次开始...

  • 最大数组长度为 45。
  • 最小子数组长度为 3。
  • EAccessViolation 错误通常发生在数组长度为 12-13 并且通常发生在第一个循环的最后一次迭代中。

再一次,我知道算法逻辑本身存在缺陷,但我真的想先修复内存问题。

非常感谢。

function TfrmMain.Ready(Numbers: Array of SmallInt): SmallInt;
var
  i: Integer;
  Length, MinLength, MaxLength: SmallInt;
  Array1, Array2: Array of SmallInt;
  Array1Pos, Array1FirstPos, Array1LastPos: Integer;
  Array2Pos, Array2FirstPos, Array2LastPos: Integer;
begin
  Result := 0;

  MinLength := 3;
  MaxLength := Trunc( (High(Numbers) + 1 ) / 2 );

  for Length := MinLength to MaxLength do
  begin
    SetLength(Array1, 0);
    SetLength(Array2, 0);

    SetLength(Array1, Length);

    Array1FirstPos := 0;
    Array1LastPos  := High(Numbers) - High(Array1);

    for Array1Pos := Array1FirstPos to Array1LastPos do
    begin
      for i := Array1Pos to Length + Array1Pos do
        Array1[i - Array1Pos] := Numbers[i];

      if ( High(Array2) + 1 <> Length ) then
        SetLength(Array2, Length);

      Array2FirstPos := Array1Pos + Length;
      Array2LastPos  := High(Numbers);

      if ( ( Array1Pos >= Array2FirstPos ) and ( Array1Pos + Length <= Array2LastPos ) ) then
        for Array2Pos := Array2FirstPos to Array2LastPos do
        begin
          for i := Array2Pos to Length + Array2Pos do
            Array2[i - Array2Pos] := Numbers[i];

          if CompareArrays(Array1, Array2) then
            Result := Result + 1;
        end;
    end;
  end;

  SetLength(Array1, 0);
  SetLength(Array2, 0);
end;

function TfrmMain.CompareArrays(Array1, Array2: Array of SmallInt): Boolean;
var
  i: Integer;
begin
    Result := false;

  if ( High(Array1) <> High(Array2) ) then
    Exit;

  for i := 0 to High(Array1) do
    if ( Array1[i] <> Array2[i] ) then
        Exit;

    Result := true;
end;

已解决!谢谢杰弗森奥利维拉!

【问题讨论】:

  • 发生错误时如何调用“Ready”方法(使用哪些参数)?在哪一行引发了异常?
  • @Jeferson Oliveira 我得到一个 Memo.Text,在其上应用 ExtractStrings 以删除空格,然后通过强制转换 ShortString 数组的每个成员来填充 SmallInt 数组。随机 SetLengths 引发异常。有时它发生在代码中间,有时在最后一个之后……谢谢大家的关注。

标签: arrays delphi memory dynamic


【解决方案1】:

引发的错误取决于您传递的数组的内容,所以如果您能向我们展示一个调用示例或您的备忘录的内容会更好。

不管怎样,分析你的代码,我可以看到一些东西:

在下面一行:

  if ( High(Array2) + 1 <> Length ) then
    SetLength(Array2, Length);

如果 Length = 0,或 Length = High(Array2) + 1,则不会定义 Array2 长度。

因此,当执行下面的代码时:

  if ( ( Array1Pos >= Array2FirstPos ) and ( Array1Pos + Length <= Array2LastPos ) ) then
    for Array2Pos := Array2FirstPos to Array2LastPos do
    begin
      for i := Array2Pos to Length + Array2Pos do
        Array2[i - Array2Pos] := Numbers[i];

如果 Array2 的长度尚未定义,您可能会遇到 AccessViolation。 因此(仅出于修复此代码的目的),您应该在尝试访问其索引之前测试 Array2 的长度:

for i := Array2Pos to Length + Array2Pos do
begin
    if ((i - Array2Pos) >= System.Length(Array2) - 1) then
        Array2[i - Array2Pos] := Numbers[i];
end;

但我相信,专注于您的逻辑并组织一些测试值,您会发现需要对您的代码进行大量改进,这些代码本身将解决当前的 AV。

已编辑:由于您的变量与全局函数“Length”同名,我将示例代码更新为使用“命名空间”系统。

【讨论】:

  • 你,先生,真是天赐之物。我的错误正是你提到的,但使用 Array1 而不是 Array2。我花了足够长的时间才注意到,现在我觉得自己很愚蠢,哈哈。非常感谢您的支持。我知道逻辑缺陷,我现在要修复它们。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多