I have this following C++ code:
#include <Windows.h>
#include <type_traits>
class Sample
{
decltype(&ActivateActCtx) ActivateActCtx;
decltype(&ReadFile) ReadFile;
decltype(&WriteFile) WriteFile;
template <typename F>
static void ResolveFunction(F& output, const char* name)
{
static auto handle{ GetModuleHandleW(L"kernel32.dll") };
if (!((output = reinterpret_cast<F>(GetProcAddress(handle, name)))))
throw name;
}
public:
Sample()
{
ResolveFunction(ActivateActCtx, "ActivateActCtx");
ResolveFunction(ReadFile, "ReadFile");
ResolveFunction(WriteFile, "WriteFile");
}
template <typename T>
constexpr T Get()
{
if constexpr (std::is_same_v < T, decltype(&::ReadFile)>)
return ReadFile;
if constexpr (std::is_same_v < T, decltype(&::WriteFile)>)
return WriteFile;
if constexpr (std::is_same_v < T, decltype(&::ActivateActCtx)>)
return ActivateActCtx;
return {};
}
};
int main()
{
Sample s;
s.Get<decltype(&ReadFile)>()(nullptr, nullptr, 0, nullptr, nullptr);
s.Get<decltype(&WriteFile)>()(nullptr, nullptr, 0, nullptr, nullptr);
s.Get<decltype(&ActivateActCtx)>()(nullptr, nullptr);
return 0;
}
As you can see auto handle{ GetModuleHandleW(L"kernel32.dll") }; is static and should be assigned with the return value of GetModuleHandleW just once. However, upon disassembly of the program it seems to be assigned three times, for each call in the constructor. I know that an implicit inline is before ResolveFunction, but I don't think that should literally inline so aggressively so that the definition of static is violated.
I am using Microsoft Visual C++ 19.32.31329. Optimization settings: /O2 /Oi /GL I also tried maximum optimization for size and got the same result. Everything is compiled as Release of course.

