DelphiGetLogicalProcessorInformationx64
奇怪的是,这段在 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;
回答
在第一次调用之前ReturnLength,您没有使用您的大小进行初始化,从而导致未定义的行为。根据文档,该参数是输入/输出参数:BufferGetLogicalProcessorInformation()
返回长度
在输入时,指定指向的缓冲区的长度
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) 错误的情况下进行操作。当您调用undefined behavior 时,实际上任何事情都可能发生,包括看似正确的行为。
THE END
二维码