【问题标题】:Delphi GetLogicalProcessorInformation x64Delphi GetLogicalProcessorInformation x64
【发布时间】:2021-02-10 02:41:02
【问题描述】:

奇怪的是,这段在 Delphi X32 下运行良好的代码在 x64 编译时却无法运行。 对 GetLogicalProcessorInformation 的第一次调用只是返回代码 988(对内存位置的访问无效),我想知道为什么,以及可以采取什么措施来克服这个问题。


function GetLogicalProcessorInfo : TLogicalProcessorInformation;
var
  i           : Integer;
  ReturnLength: DWORD;
  Buffer      : array of TSystemLogicalProcessorInformation;

begin

  result.LogicalProcessorCount := 0;
  result.NumaNodeCount         := 0;
  result.ProcessorCoreCount    := 0;
  result.ProcessorL1CacheCount := 0;
  result.ProcessorL2CacheCount := 0;
  result.ProcessorL3CacheCount := 0;
  result.ProcessorPackageCount := 0;

  SetLength(Buffer,256);

  if not GetLogicalProcessorInformation(@Buffer[0], ReturnLength) then
  begin
    if GetLastError = ERROR_INSUFFICIENT_BUFFER then
    begin
      SetLength(Buffer,ReturnLength div SizeOf(TSystemLogicalProcessorInformation) + 1);
      if not GetLogicalProcessorInformation(@Buffer[0], ReturnLength) then
        RaiseLastOSError;
    end
    else
      RaiseLastOSError;
  end;

  SetLength(Buffer, ReturnLength div SizeOf(TSystemLogicalProcessorInformation));

  for i := 0 to High(Buffer) do begin
    case Buffer[i].Relationship of
        RelationNumaNode: Inc(result.NumaNodeCount);
        RelationProcessorCore:
          begin
            Inc(result.ProcessorCoreCount);
            result.LogicalProcessorCount := result.LogicalProcessorCount + CountSetBits(Buffer[i].ProcessorMask);
          end;
        RelationCache:
          begin
            if (Buffer[i].Cache.Level = 1) then Inc(result.ProcessorL1CacheCount)
            else if (Buffer[i].Cache.Level = 2) then Inc(result.ProcessorL2CacheCount)
            else if (Buffer[i].Cache.Level = 3) then Inc(result.ProcessorL3CacheCount);
          end;
        RelationProcessorPackage: Inc(result.ProcessorPackageCount);
        else
          raise Exception.Create('Error: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.');
    end;
  end;

end;

【问题讨论】:

    标签: delphi 64-bit


    【解决方案1】:

    在第一次调用GetLogicalProcessorInformation() 之前,您没有使用Buffer 的大小初始化ReturnLength,导致未定义的行为。根据documentation,该参数是输入/输出参数:

    返回长度

    在输入时,指定Buffer 指向的缓冲区的长度,以字节为单位。 如果缓冲区足够大以包含所有数据,则此函数成功并且ReturnLength 是设置为返回的字节数。如果缓冲区不够大,无法包含所有数据,则函数失败,GetLastError 返回ERROR_INSUFFICIENT_BUFFER,并且ReturnLength 设置为包含所有数据所需的缓冲区长度。如果函数因ERROR_INSUFFICIENT_BUFFER 以外的错误而失败,则ReturnLength 的值未定义。

    您需要添加该初始值,例如:

    SetLength(Buffer,256);
    
    ReturnLength := SizeOf(TSystemLogicalProcessorInformation) * 256; // <-- ADD THIS!
    
    if not GetLogicalProcessorInformation(@Buffer[0], ReturnLength) then
    ...
    

    您的代码完全可以在 32 位下运行,这是一种侥幸。很有可能,ReturnLength 只是从调用堆栈中取出一个 随机值,该值恰好允许 GetLogicalProcessorInformation() 运行而不会导致 ERROR_NOACCESS (998) 错误。当您调用未定义的行为时,实际上任何事情都可能发生,包括看似正确的行为。

    【讨论】:

    • 你找到了。我错过了这个参数是一个输入/输出参数......现在它工作正常。
    • 非常感谢雷米!
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多