为什么 GetLastError 在我的程序开始之前就出错了?

Why does GetLastError have an error before my program begins?

在调用像 ExtractShortPathName 这样的 Windows API 函数包装器后使用 GetLastError 时,我注意到 GetLastError returns 是一个非零值错误代码,无论对 ExtractShortPathName 的调用是成功还是失败。事实上,在我的程序执行之前似乎有一个 "last error",例如

program TestGetLastError;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

var
  ErrorCode: Integer;

begin
  try
    ErrorCode := GetLastError;
    if ErrorCode <> 0 then
      RaiseLastOSError;
  except
    on E: Exception do
      WriteLn(E.ClassName, ': ', E.Message);
  end;
end.

结果:

EOSError: System Error.  Code: 122.
The data area passed to a system call is too small

我是误会了什么还是做错了什么?

如果 Delphi 运行-time 正在做一些导致 GetLastError 被设置的事情,那么在我的程序开始执行之前清除该错误的正确方法是什么?我应该像 Delphi API 文档中的这个例子那样使用 SetLastError(ERROR_SUCCESS); 吗:

procedure TForm2.btRaiseLastClick(Sender: TObject);
begin
  { Set the last OS error to a bogus value. }
  System.SetLastError(ERROR_ACCESS_DENIED);

  try
    RaiseLastOSError();
  except
    on Ex : EOSError do
      MessageDlg('Caught an OS error with code: ' + IntToStr(Ex.ErrorCode), mtError, [mbOK], 0);
  end;

  { Let the Delphi Exception dialog appear. }
  RaiseLastOSError(ERROR_NOT_ENOUGH_MEMORY);

  { Finally set the last error to none. }
  System.SetLastError(ERROR_SUCCESS);

  if GetLastError() <> ERROR_SUCCESS then
    MessageDlg('Whoops, something went wrong in the mean time!', mtError, [mbOK], 0);

  { No exception should be thrown here because last OS error is "ERROR_SUCCESS". }
  CheckOSError(GetLastError());
end;

http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/LastOSError_(Delphi)

GetLastError() 编辑的值 return 仅在 Windows API 调用失败后立即相关,并且该函数的文档指定了扩展错误可通过致电 GetLastError().

获取信息

在该上下文之外调用它会 return 之前调用的内容,可能来自您的代码、Delphi 运行时、您调用的 DLL 甚至 Windows API...

Windows API 文档 GetLastError() 指出:

You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data.

GetLastError 的文档表明只有在

时才有用
  • 一个 API 调用失败,并且
  • 失败的函数表明您可以使用 GetLastError 获取有关原因的更多信息。 来自该文档(强调我的

The return value is the calling thread's last-error code.

The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread's last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.

这表明在没有首先在记录为将其设置为失败的函数中发生故障的情况下调用它是没有意义的。您不能调用 GetLastError,除非您知道发生了错误,并且只有在您调用的特定函数指示失败后才调用它。