-
Notifications
You must be signed in to change notification settings - Fork 30k
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
Pragma "section(".CRT$XCU", read)" can prevent global variable dynamic initialization #41852
Comments
I also wondered, is there any workaround for this in the meantime? Is there any other way to register a node module that doesn't touch this #pragma logic? (Or I can just not use |
I also opened a ticket with Microsoft about the "pragma section" doing this garbage collection of variable initializers: https://developercommunity.visualstudio.com/t/pragma-sectionCRTXCU-read-garbag/1654499 |
@nodejs/node-api |
We briefly discussed this in the 11 Feb Node API meeting. This pragma has been present in |
I guess this is just a copy of the corresponding code in node.h. Maybe it could be fixed by something like this which uses C++ style initialization in case file is compiled as C++ instead the crt section hack: #if defined(__cplusplus)
#define NAPI_C_CTOR(fn) \
static void __cdecl fn(); \
struct napi_init_helper { \
napi_init_helper() { fn(); } \
}; \
static napi_init_helper init_helper; \
static void __cdecl fn()
#else
#pragma section(".CRT$XCU", read)
#define NAPI_C_CTOR(fn) \
static void __cdecl fn(void); \
__declspec(dllexport, allocate(".CRT$XCU")) void(__cdecl * fn##_)(void) = \
fn; \
static void __cdecl fn(void)
#endif Moving the pragma into the macro didn't work for me. Besides that it seems to be just a partial fix as it likely stops working if |
In the last Node-API meeting on 3/4/2022 I was tasked to look into details of this issue. The best fix is to completely remove use of the section and replace it with a normal static variable initialization similar to what @Flarna proposes above. I would suggest a few small corrections to that code:
#define NAPI_C_CTOR(fn) \
static void __cdecl fn(); \
struct napi_init_helper_##fn { \
napi_init_helper() { fn(); } \
} napi_init_helper_inst_##fn; \
static void __cdecl fn() As a minimal change, we must replace use of the |
This StackOverflow article is addressing the same issue: |
This issue was discussed in Node-API meeting today 3/11/2022. |
I don't think it's needed to be C only. There must be a C variant but by using |
Edited: @Flarna, yes, you are right: the struct-based approach can work only for C++ and thus we better use the anonymous namespace to match the |
Closing as PR to address was landed |
Awesome! Thanks for working on this. |
Version
v16.6.0
Platform
Microsoft Windows NT 10.0.19043.0 x64
Subsystem
Node API
What steps will reproduce the bug?
Compile this C++ with MSVC (c++17 required)
Then run
node -e "require('./path/to/addon')"
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior?
The expected behavior is for the reproduction steps above to print out
The value of the string is 123
.What do you see instead?
The reproduction steps above print out
The value of the string is
. This happens because the initializer for theinline
variabletestString
is optimized out. Apparently it is optimized out because of the line#pragma section(".CRT$XCU", read)
innode_api.h
. When I remove that pragma, the program works as expected.See this blog for more details on why pragma
section
can cause this behavior: https://devblogs.microsoft.com/cppblog/new-compiler-warnings-for-dynamic-initialization/Additional information
Why is the pragma needed? Can it be removed? If it is required only in certain conditions, maybe it could be inside an
#ifdef
check?If the pragma is always required but only for the definition of the module registration logic, perhaps the pragma could go inside the
NAPI_C_CTOR
macro by using the standard_Pragma
directive like this:Either removing the pragma or placing it inside of
NAPI_C_CTOR
fixes the bug (though the bug would probably reappear if an inline was used below the module registration logic).The text was updated successfully, but these errors were encountered: