-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Describe the bug
I use the AWS SDK dll's on Windows in a binary that can also run outside the cloud on arbitrary windows systems.
Support for AWS was added a few years ago and we used the DelayLoadDLLs directive when building our binaries so the DLL's are not required in a non-AWS environment (and not used/loaded even in AWS until it actually uses AWS functionality).
After an upgrade to the latest AWS SDK this was broken: The linker told me I could not use the DelayLoadDLLs for the AWS dll's because of the "g_allocator" symbol.
4>LINK : fatal error LNK1194: cannot delay-load 'aws-crt-cpp.dll' due to import of data symbol '"__declspec(dllimport) struct aws_allocator * Aws::Crt::g_allocator" (_imp?g_allocator@Crt@Aws@@3PEAUaws_allocator@@ea)'; link without /DELAYLOAD:aws-crt-cpp.dll
Digging through the AWS source I found the culprit: aws/crt/StlAllocator.h has the line:
extern AWS_CRT_CPP_API Allocator *g_allocator;
Which implies that any component that includes AWS header files ends up with an extern DATA reference to the g_allocator.
The DelayLoadDLLs can handle references to functions, but because the value of g_allocator must be resolved at start-time of the binary, this one single pointer caused our product to have a very undesirable hard runtime dependency with AWS.
I did a crude hack to get around this. I replaced the "extern" line with this:
extern AWS_CRT_CPP_API Allocator *Get_g_allocator();
#define g_allocator Get_g_allocator()
So everywhere the code uses "g_allocator" it now calls a getter function for the current value.
In crt/aws-crt-cpp/source/Api.cpp (where g_allocator is defined) I added (after the #includes):
/* Undo hack in StlAllocator.h */
#ifdef g_allocator
#undef g_allocator
#else
#error StlAllocator must define g_allocator as a call to Get_g_allocator()
#endif
The #error is just to make sure my includes and defines and up as intended.
The getter function is trivial:
AWS_CRT_CPP_API Allocator *Get_g_allocator();
Allocator *Get_g_allocator() { return g_allocator; }
Building with these modified header files yields a working configuration that no longer suffers from the hard dependency.
The hack is, of course, ugly as sin.
But because there are some 53 uses of "g_allocator" in a some 20 different files, I did it the quick & dirty way.
Expected Behavior
That we could have a single binary that optionally uses AWS dll's (like was possible in an older version of the AWS SDK).
Current Behavior
Linking a Windows binary that uses DelayLoadDLLs on aws-sdk-core.dll yields this error:
4>LINK : fatal error LNK1194: cannot delay-load 'aws-crt-cpp.dll' due to import of data symbol '"__declspec(dllimport) struct aws_allocator * Aws::Crt::g_allocator" (_imp?g_allocator@Crt@Aws@@3PEAUaws_allocator@@ea)'; link without /DELAYLOAD:aws-crt-cpp.dll
Reproduction Steps
The code is not the problem: Try linking a binary that has a DelayLoadDLLs in the vcxproj files likes this:
aws-cpp-sdk-core.dll
And get the error about the DelayLoad not being possible because of the g_allocator symbol.
Possible Solution
Change all occurrences of g_allocator in the header files to a function call that returns the current value.
Additional Information/Context
The (crude) patch provides a workaround for us, so it is currently not an urgent issue.
But I'd like to see a fix for this in a future version.
AWS CPP SDK version used
git clone from April 25, 2022.
Compiler and Version used
Visual Studio 2019
Operating System and version
Windows 2016