Delphi - 为什么我会收到此访问冲突? ADOQuery 参数有限制吗?

标签 delphi access-violation tadoquery

我有这个返回访问冲突的代码('sqloledb.dll' 模块中地址 74417E44 的访问冲突。读取地址 786E3552'),我无法确定问题出在哪里。我唯一的猜测是 ADOQuery 对我们可以传递的参数数量有限制。
代码如下:

With qryInsert do
  begin
    Active := False;
    Close;
    Sql.Clear;
    Sql.Add('Insert Into MyTable(ColumnOne, ');
    Sql.Add('             ColumnTwo,           ');
    Sql.Add('             ColumnThree,         ');
    Sql.Add('             ColumnFour,           ');
    Sql.Add('             ColumnFive,          ');
    Sql.Add('             ColumnSix,        ');
    Sql.Add('             ColumnSeven,        ');
    Sql.Add('             ColumnEight,     ');
    Sql.Add('             ColumnNine,       ');
    Sql.Add('             ColumnTen,       ');
    Sql.Add('             ColumnEleven,     ');
    Sql.Add('             ColumnTwelve,   ');
    if qrySelect.FieldByName('ColumnTwelve').AsSTring = 'Y' then
    begin
      Sql.Add('           ColumnThirteen,   ');
      Sql.Add('           ColumnFourteen,   ');
      Sql.Add('           ColumnFifteen,   ');
    end;
    Sql.Add('             ColumnSixteen,   ');
    if qrySelect.FieldByName('ColumnSixteen').AsSTring = 'Y' then
    begin
      Sql.Add('           ColumnSeventeen,         ');
      Sql.Add('           ColumnEighteen,         ');
      Sql.Add('           ColumnNineteen,         ');
    end;
    if qrySelect.FieldByName('ColumnTwenty').AsSTring = 'Y' then
    begin
      Sql.Add('           ColumnTwenty,  ');
      Sql.Add('           ColumnTwentyOne,        ');
      Sql.Add('           ColumnTwentyTwo,        ');
      Sql.Add('           ColumnTwentyThree,        ');
    end
    else
      Sql.Add('           ColumnTwenty,  ');
    Sql.Add('             ColumnTwentyFour) ');
    Sql.Add('Values(:ColumnOne, :ColumnTwo, :ColumnThree, :ColumnFour, ');
    Sql.Add('       :ColumnFive, ' + dateDB + ', :ColumnSeven,          ');
    Sql.Add('       :ColumnEight, :ColumnNine, :ColumnTen, ');
    Sql.Add('       :ColumnEleven,                                    ');
    Sql.Add('       :ColumnTwelve,                                    ');
    if qrySelect.FieldByName('ColumnTwelve').AsSTring = 'Y' then
      Sql.Add('     :ColumnThirteen, :ColumnFourteen, :ColumnFifteen,              ');
    Sql.Add('       :ColumnSixteen,                                      ');
    if qrySelect.FieldByName('ColumnSixteen').AsSTring = 'Y' then
      Sql.Add('     :ColumnSeventeen, :ColumnEighteen, :ColumnNineteen,                 ');
    if qrySelect.FieldByName('ColumnTwenty').AsSTring = 'S' then
    begin
      Sql.Add('   :ColumnTwenty,                                      ');
      Sql.Add('   :ColumnTwentyOne, :ColumnTwentyTwo, :ColumnTwentyThree,                ');
    end
    else
      Sql.Add('   :ColumnTwenty,                                      ');
    Sql.Add('     :ColumnTwentyFour)                                  ');
    {And then for all the parameteres, pass the value}
    Parameters.ParamByName('ColumnOne').Value := varColumnOne;
    ...
    Parameters.ParamByName('ColumnTwentyFour').Value := varColumnTwentyFour;
    ExecSQL;
  end;

我在这一行收到错误:
Sql.Add('       :ColumnTwelve,                                    ');

这是我的插入语句中的第 11 个参数。
如果我评论这一行,我会在下一个参数中得到错误。
如果我像这样直接输入值:
Sql.Add('     ' + varColumnTwelve + ',                            ');

它工作正常,但我在下一个参数中收到错误。

所以这让我想知道:ADOQuery 对它可以处理的参数数量有限制吗?或者,如果这不是真正的问题,有没有人知道我如何解决这个问题?

笔记:
  • 我使用的是 Delphi 7 和 Windows 8.1。
  • AV 仅(并且始终)在调试时出现,如果我直接通过其“.exe”执行应用程序,则它永远不会出现。
  • 如果我在出现错误后一直按“运行”,它会显示越来越多的AV(我认为AV的数量与第10个之后添加的参数数量相同),直到应用程序继续正常运行。
  • 在所有 AV 都出现在屏幕上之后,插入 工作 。我只是想了解为什么当一切正常时我会收到此错误。
  • 最佳答案

    The AV only (and always) appears when debugging, it does never appear if I execute the application directly through its ".exe".

    ....

    The insert works after all the AVs appeared on the screen. I just want to understand why am I getting this error when everything looks fine.



    访问冲突是在外部模块中引发的,该模块是用 Delphi 以外的语言实现的。很可能外部代码按照设计正确运行,并且预计会出现访问冲突。

    这听起来可能很奇怪,但外部代码清楚地处理了异常,因为控制权不会传递给代码的异常处理程序。如您所见,该程序运行正常。

    这就是所谓的 first chance exception 。调试器被通知并中断。但随后控制权返回给程序,在这种情况下,程序处理异常并继续。代码引发第一次机会访问冲突异常,但仍然正常运行,这是完全正常的,尽管可能违反直觉。作为该声明的证据,请从 VS 开发团队成员编写的 article 中看到这一点:

    Why the VS Debugger does not stop on first chance Access Violations (by default)?

    ....

    The reason the default for first-chance AVs does not stop is that sometimes Windows calls will AV, and then catch the exception themselves and carry on happily. If we did default to stopping on first chance AVs we would stop users in some strange place in say kernel32.dll and many would be very confused.



    所以就正确性而言,我认为没有什么可担心的。但它确实使调试变得困难。尝试@Deltics 提出的各种建议。如果通过进行这些更改,您碰巧避免了异常,那就太好了。否则,您可能需要至少暂时禁止调试器中断异常。

    关于Delphi - 为什么我会收到此访问冲突? ADOQuery 参数有限制吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30305578/

    相关文章:

    Delphi FMX 组件重影删除子组件

    windbg - 这些问号在 Windbg 中是什么意思?

    c# - 调用 IStorage 的 EnumElements 时发生访问冲突

    multithreading - 在线程中使用TADOQuery

    delphi - 如何将 TMemo 组件中的多行添加到 MS Access 数据库?

    delphi - 哪个更好 : Free or FreeAndNil?

    delphi - 使用 Indy 10.5.8 进行 POST 时标题中出现垃圾

    delphi - 如何将参数传递给 ADOQuery 对象?

    delphi - 无法打开项目: "One or more lines were too long and have been truncated"

    c# - COM/DCOM : Server stub does not allocate memory for new methods in existing interface