我有一个返回SYSTEMTIME的函数。
function GetFileDate : SYSTEMTIME; //Stdcall;
var
CheckFile: Long;
FileTime: LPFILETIME;
FileTimeReturn: LPFILETIME;
SystemTimeReturn: LPSYSTEMTIME;
begin
CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(CheckFile, @FileTime, NIL, NIL);
FileTimeToLocalFileTime(@FileTime, @FileTimeReturn);
FileTimeToSystemTime(@FileTime, @SystemTimeReturn);
GetFileDate := SystemTimeReturn^;
end;
对于2012年和2006年的两个文件以及其他任何内容,它总是返回97年。 为什么呢?
答案 0 :(得分:3)
那段代码是无稽之谈,我很惊讶它完全可以编译。你声明了三个指针变量,但是你从不让它们指向任何东西。您将指向这些变量的指针传递给API函数,但这些API函数不会指向指向它们的类型的指针。
FileTimeToLocalFileTime
预计会收到两个FILETIME
指针。您已将FileTime
和FileTimeReturn
声明为FILETIME
值的指针,但当您将@
运算符应用于它们时,您会得到指针指向FILETIME
值的指针。更好的代码应如下所示:
function GetFileDate : SYSTEMTIME; //Stdcall;
var
CheckFile: Long;
FileTime: FILETIME;
FileTimeReturn: FILETIME;
SystemTimeReturn: SYSTEMTIME;
begin
CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(CheckFile, @FileTime, NIL, NIL);
FileTimeToLocalFileTime(@FileTime, @FileTimeReturn);
FileTimeToSystemTime(@FileTime, @SystemTimeReturn);
GetFileDate := SystemTimeReturn;
end;
请注意,我已从类型名称中删除了LP
前缀,并且已从最后一行中删除了取消引用。
正确的代码会检查每个API函数的返回值,以确保它在调用下一个函数之前成功。
这就是为什么你会看到意想不到的结果。 FILETIME
是64位值。如果您使用的是32位系统,则LPFILETIME
变量仅为32位宽。 API需要一个指向64位宽缓冲区的指针,但是你给它一个指向32位空间的指针。当API将64位信息写入32位空间时,我们无法确定存储额外32位的位置。
您传递了指向SystemTimeReturn
的指针,该指针是LPSYSTEMTIME
。 API写入该空间就好像它是SYSTEMTIME
一样。然后,您的函数取消引用它假定为LPSYSTEMTIME
的内容,但实际上保留了SYSTEMTIME
类型的值。你取消引用时间而不是指针。你得到的时间看起来像一个有效的地址,居住在那个“地址”的值恰好是97.