I am designing a library where I need AWS SDK for S3 and Kinesis as wrapped sub-components. In an executable, Aws::InitAPI() and Aws::ShutdownAPI() can be called once, so I am trying to design a wrapper which can call Init and Shutdown only one time for any number of components.
Consider the following example. Only when declared as a global shared_ptr, when the shutdown API is called, the application crashes.
To recreate the issue, you can uncomment the start 4, compile, and run.
#include <thread>
#include <aws/core/Aws.h>
namespace axon {
class AwsStack {
Aws::SDKOptions options;
public:
AwsStack() {
options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
printf("Aws::SDK::Init()\n");
Aws::InitAPI(options);
}
~AwsStack() {
printf("Aws::SDK::Shutdown()\n");
Aws::ShutdownAPI(options);
}
};
};
std::shared_ptr<axon::AwsStack> awsInstance1;
int main(int argc, char** argv)
{
// // start 1
// axon::AwsStack awsInstance0; // this does not crash
// // end
// // start 2
// std::shared_ptr<axon::AwsStack> awsInstance2 = std::make_shared<axon::AwsStack>(); // this does not crash
// // end
// // start
// awsInstance1 = std::make_shared<axon::AwsStack>(); // this does not crash
// awsInstance1.reset();
// // end
// // start
// awsInstance1 = std::make_shared<axon::AwsStack>(); // but this will crash
// // end
return 0;
}
Compiled with following:
c++ -ggdb -o example example.cpp -laws-cpp-sdk-core
Any thoughts about why it crashes? How can I fix it?
This is some kind of initialization order fiasco. The case 4 is specifically mention in the manual Initializing and shutting down the AWS SDK for C++. Just don't do that.
The SDK for C++ and its dependencies use C++ static objects, and the order of static object destruction is not determined by the C++ standard. To avoid memory issues caused by the nondeterministic order of static variable destruction, do not wrap the calls to
Aws::InitAPIandAws::ShutdownAPIinto another static object.
Possible dup: Destruction order of static objects in C++