c++amazon-web-servicesmemorycrashaws-sdk-cpp

Aws::ShutdownAPI crashes when called by shared_ptr


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?


Solution

  • 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::InitAPI and Aws::ShutdownAPI into another static object.

    Possible dup: Destruction order of static objects in C++