【问题标题】:What all APIs are affected by {$IOCHECKS OFF}?{$IOCHECKS OFF} 会影响哪些 API?
【发布时间】:2009-07-09 22:13:44
【问题描述】:

我们有一些古老的 Delphi 代码(甚至可能起源于 Turbo Pascal 代码)使用 {$I-},又名 {$IOCHECKS OFF},这使得代码使用 IOResult 而不是磁盘 I 的异常/O 错误。

我想摆脱{$I-} 并将这段代码带到1990 年代,但要做到这一点,我想知道{$IOCHECKS OFF} 会影响什么。这只影响像AssignFile/Reset/Rewrite/Append/CloseFile这样笨拙的旧内置I/O函数吗?或者它是否也会影响更现代的东西,比如 TFileStream?更重要的是,还有什么我没有想到的可能会受到影响? (Delphi Basics 暗示它也会影响 MkDir 和 RmDir。如果它影响到这些,那么必须有更多。)

Delphi 2007 帮助主题“输入输出检查 (Delphi)”(ms-help://borland.bds5/devcommon/compdirsinput_outputchecking_xml.html) 说这会影响“I/O 过程[s]”,并且“I/O 过程在 Delphi 语言指南中进行了描述。 "这并没有多大帮助,因为 CodeGear 从未发布过语言指南,而 Borland 上一次发布语言指南是 Delphi 5。

{$I-} 下哪些函数和类的行为不同?


编辑:接受的答案提供了一些很好的背景,但这里是按字母顺序排列的列表形式的快速摘要:{$IOCHECKS OFF} 影响系统单元的以下例程。

  • 追加
  • 块读取
  • 块写入
  • ChDir
  • 关闭文件
  • Eof
  • 埃隆
  • 擦除
  • 文件位置
  • 文件大小
  • 冲洗
  • MkDir
  • 阅读
  • 阅读
  • 重命名
  • 重置
  • 重写
  • RmDir
  • 寻找
  • SeekEof
  • SeekEoln
  • 设置LineBreakStyle
  • 截断

【问题讨论】:

    标签: delphi file-io error-handling compiler-directives


    【解决方案1】:

    由于$I是编译器指令,它只能影响编译器生成的代码,也只能影响实际编译的代码。

    由于这两个原因,它不能影响TFileStream 之类的东西。它是Classes.pas 中的一个类,它是一个你不编译的单元。其中的任何代码都不受$I 指令的影响。此外,编译器不会以任何方式特别对待该类。这只是另一个普通的课程。

    $I 指令会影响您提到的语言内置函数。编译器专门生成对这些函数的调用。它还会影响对writewritelnreadln 的调用。它也会影响BlockReadBlockWrite

    您可以查看源代码。任何调用SetInOutRes 的东西都容易受到$I 的影响。这包括打开文件的函数(AppendResetRewrite),以及接受 fileTextFile 类型参数的任何其他函数(FlushBlockRead、@987654339 @,Erase,FilePos,Seek,FileSize,Read,Readln,Write,Writeln,Rename,Eof,Eof,Eof,@9876 SeekEolTruncateSetLineBreakStyleCloseFile)。此外,任何调用 InOutErrorChDirMkDir、amd RmDir)的东西。

    列表中明显缺席的是AssignFile。该函数实际上并不执行任何 I/O。它只是设置文件记录,以便AppendResetRewrite 知道该怎么做。


    我应该指出,查看源代码只是推理。 $I 指令控制在您调用某些其他函数后,编译器是否会在您自己的代码中插入对__IOTest 函数的调用。该函数检查InOutRes 的值,如果它不为零,则会引发运行时错误(如果SysUtils 包含在您的程序中,则可能会产生异常)。我们无法直接查看源代码来找出哪些函数受到$I的影响(因为它只在编译器生成的代码中调用),所以我们实际上只是在寻找哪些函数set InOutRes,假设如果他们不知道编译器会在之后检查它,他们就不会费心去做。

    【讨论】:

    • 甜蜜 - 很高兴知道如何追踪这些(很遗憾,那里有很多 _Read*_Write* 方法!)。不过,您似乎错过了三个:SetLineBreakStyleSeekEofSeekEoln
    • 另外值得注意的是,这只影响系统单元中的例程。没有其他人调用SetInOutResInOutError
    • 所有_Read*_Write* 都在那里,因为ReadWrite 是编译魔法。编译器为您传递给ReadWrite每个参数 插入一个对专用函数的调用。如果启用了$I,它会插入对__IOTest 的调用。
    猜你喜欢
    • 2013-12-11
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 2015-10-20
    相关资源
    最近更新 更多