std::chrono::system_time 的 Visual Studio 2017 CRT 实现使用什么时钟?

Jor*_*den 5 c++ windows visual-c++

chrono 标题中的评论只是说

// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
Run Code Online (Sandbox Code Playgroud)

但它实际使用哪个(即我可以期望什么精度)?该实现调用_Xtime_get_ticks,但该函数是不透明的。

Axa*_*alo 4

CRTGetSystemTimePreciseAsFileTime在可用时调用,GetSystemTimeAsFileTime否则调用。 GetSystemTimePreciseAsFileTime为您提供尽可能高的精度(<1us)

在运行时初始化期间,有时initialize_pointers会调用一个名为的函数,该函数基本上执行以下操作(反编译和简化):

HMODULE hModule = GetModuleHandleW(L"kernel32.dll");

__encodedKERNEL32Functions[0] = (void *)GetProcAddress(hModule, "FlsAlloc");
__encodedKERNEL32Functions[1] = (void *)GetProcAddress(hModule, "FlsFree");
__encodedKERNEL32Functions[2] = (void *)GetProcAddress(hModule, "FlsGetValue");
__encodedKERNEL32Functions[3] = (void *)GetProcAddress(hModule, "FlsSetValue");

...


__encodedKERNEL32Functions[24] = (void *)GetProcAddress(hModule, "GetSystemTimePreciseAsFileTime");

...
Run Code Online (Sandbox Code Playgroud)

在 Windows 8 或更高版本的系统上将__encodedKERNEL32Functions[24]非零。

然后归结为:

std::chrono::system_clock::now()
-> _Xtime_get_ticks
   -> __crtGetSystemTimePreciseAsFileTime(FILETIME *)

void __crtGetSystemTimePreciseAsFileTime(FILETIME *lpSystemTimeAsFileTime)
{
    void (*f)(FILETIME *) = (void (*)(FILETIME *))__encodedKERNEL32Functions[24];
    if (f)                         // if GetSystemTimePreciseAsFileTime exists
        f(lpSystemTimeAsFileTime); // call it
    else
        GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
}
Run Code Online (Sandbox Code Playgroud)

至少这是(大约)在14.16.27024.1版本的msvcp140.dllmsvcp140d.dll中实现的方式。

当然,所有这些都没有记录,并且可能会发生变化。

如果您需要使用,GetSystemTimePreciseAsFileTime您应该编写自己的时钟,而不是依赖于实现细节。