-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Fix call to CreateFileMappingW. #1902
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The call shouldn't rely on the `size` variable, since it is available only conditionally, based on preprocessor macros. The `dwMaximumSize{High,Low}` arguments are actually optional, so omitting them. yhirose#1901
c2a6384
to
71c3d1f
Compare
@@ -2859,8 +2859,7 @@ inline bool mmap::open(const char *path) { | |||
hMapping_ = | |||
::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, size_
can be 0 as well. (I don't like it though...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For CreateFileMappingFromApp
, the documentation doesn't state that size can be 0, so I would continue passing size_
to stay aligned with the documentation : https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingfromapp
For CreateFileMappingW
, the documentation explictly states "If this parameter and dwMaximumSizeHigh are 0 (zero), the maximum size of the file mapping object is equal to the current size of the file that hFile identifies." https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got it, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you come to this code https://github.com/yhirose/cpp-httplib/pull/1902/files#diff-2324f73f4a4958b756eb44d0607268befc5de62db01164ccd73e154da808d8f3R2849-R2861? I think this block is never reached by a compiler if Windows SDK is updated (latest one w/ Windows 7).
I would remove this block completely and deal with bit shifts at LARGE_INTEGER::HighPart
. LARGE_INTEGER
is supported on Windows 7, LARGE_INTEGER::QuadPart
is not supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to my SDK's fileapi.h
:
GetFileSize
is available if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
GetFileSizeEx
is available if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
So the else block would be used if only WINAPI_PARTITION_DESKTOP
would be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the else block would be used if only
WINAPI_PARTITION_DESKTOP
would be set.
This is not true. WINAPI_PARTITION_DESKTOP
is included in WINAPI_PARTITION_APP
and #else
is never reached.
winapifamily.h:
#ifndef WINAPI_PARTITION_DESKTOP
#define WINAPI_PARTITION_DESKTOP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
#endif
#ifndef WINAPI_PARTITION_APP
#define WINAPI_PARTITION_APP \
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \
WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || \
WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
#endif
The condition
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | \
WINAPI_PARTITION_GAMES)
includes ALL Windows editions.
* +---------------------------+
* | *Partition* |
* +---+---+---+---+---+---+---+
* | | | | | | | |
* | | | | | | | |
* | | | | P | | | |
* | | | | H | | | |
* | D | | | O | | | |
* | E | | P | N | S | S | |
* | S | | C | E | Y | E | G |
* | K | | _ | _ | S | R | A |
* | T | A | A | A | T | V | M |
* +-------------------------+----+ O | P | P | P | E | E | E |
* | *Platform/Family* \| P | P | P | P | M | R | S |
* +------------------------------+---+---+---+---+---+---+---+
* | WINAPI_FAMILY_DESKTOP_APP | X | X | X | | | | |
* +------------------------------+---+---+---+---+---+---+---+
* | WINAPI_FAMILY_PC_APP | | X | X | | | | |
* +------------------------------+---+---+---+---+---+---+---+
* | WINAPI_FAMILY_PHONE_APP | | X | | X | | | |
* +----------------------------- +---+---+---+---+---+---+---+
* | WINAPI_FAMILY_SYSTEM | | | | | X | | |
* +----------------------------- +---+---+---+---+---+---+---+
* | WINAPI_FAMILY_SERVER | | | | | X | X | |
* +------------------------------+---+---+---+---+---+---+---+
* | WINAPI_FAMILY_GAMES | | | | | | | X |
* +------------------------------+---+---+---+---+---+---+---+
Could you confirm that passing 0 to the create file mapping functions dons't make any performance regression? (I guess passing length of the file explicitly performs better.) Also I don't see enough examples which pass 0 length to the APIs... |
I've run a benchmark of just creating an With size set to zero: 10011 ns with 56000 iterations. With size set explicitly: 10529 ns with 74667 iterations. |
I think this is just misprint in code. #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | \
WINAPI_PARTITION_GAMES)
LARGE_INTEGER size{};
if (!::GetFileSizeEx(hFile_, &size)) { return false; }
size_ = static_cast<size_t>(size.QuadPart);
#else
DWORD sizeHigh;
DWORD sizeLow;
sizeLow = ::GetFileSize(hFile_, &sizeHigh);
if (sizeLow == INVALID_FILE_SIZE) { return false; }
size_ = (static_cast<size_t>(sizeHigh) << (sizeof(DWORD) * 8)) | sizeLow;
#endif
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) && \
(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
hMapping_ =
::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL);
#else
hMapping_ = ::CreateFileMappingW(hFile_, NULL, PAGE_READONLY, size.HighPart,
size.LowPart, NULL);
#endif
Maybe need just Change #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | \
WINAPI_PARTITION_GAMES)
LARGE_INTEGER size{};
if (!::GetFileSizeEx(hFile_, &size)) { return false; }
size_ = static_cast<size_t>(size.QuadPart);
#else
DWORD sizeHigh;
DWORD sizeLow;
sizeLow = ::GetFileSize(hFile_, &sizeHigh);
if (sizeLow == INVALID_FILE_SIZE) { return false; }
size_ = (static_cast<size_t>(sizeHigh) << (sizeof(DWORD) * 8)) | sizeLow;
#endif to LARGE_INTEGER size{};
if (!::GetFileSizeEx(hFile_, &size)) { return false; }
size_ = static_cast<size_t>(size.QuadPart); If or to #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) && \
(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
DWORD sizeHigh;
DWORD sizeLow;
sizeLow = ::GetFileSize(hFile_, &sizeHigh);
if (sizeLow == INVALID_FILE_SIZE) { return false; }
size_ = (static_cast<size_t>(sizeHigh) << (sizeof(DWORD) * 8)) | sizeLow;
#else
LARGE_INTEGER size{};
if (!::GetFileSizeEx(hFile_, &size)) { return false; }
size_ = static_cast<size_t>(size.QuadPart);
#endif for passing size variable in same case as CreateFileMappingW |
The call shouldn't rely on the `size` variable, since it is available only conditionally, based on preprocessor macros. yhirose#1901
@yhirose _WIN32_WINNT_WIN8 not found if compile with Windows 7 SDK. This cause issue.
|
As a workaroud, the following can be added before including the header:
|
The call shouldn't rely on the
size
variable, since it is available only conditionally, based on preprocessor macros.#1901