Gerenciamento de memória no AWS SDK para C++ - AWS SDK para C++

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Gerenciamento de memória no AWS SDK para C++

O AWS SDK para C++ oferece uma maneira de controlar a alocação e desalocação de memória em uma biblioteca.

nota

O gerenciamento de memória personalizado estará disponível somente se você usar uma versão da biblioteca desenvolvida com a constante de tempo de compilação definida USE_AWS_MEMORY_MANAGEMENT.

Se você usar uma versão da biblioteca desenvolvida sem a constante de tempo de compilação, as funções globais do sistema de memória, como InitializeAWSMemorySystem, não funcionarão; em vez disso, serão usadas as funções globais new e delete.

Para acessar mais informações sobre a constante de tempo de compilação, consulte STL, strings e vetores da AWS.

Alocar e desalocar memória

Como alocar ou desalocar memória

  1. Subclasse MemorySystemInterface: aws/core/utils/memory/MemorySystemInterface.h.

    class MyMemoryManager : public Aws::Utils::Memory::MemorySystemInterface { public: // ... virtual void* AllocateMemory( std::size_t blockSize, std::size_t alignment, const char *allocationTag = nullptr) override; virtual void FreeMemory(void* memoryPtr) override; };
    nota

    É possível alterar a assinatura de tipo para AllocateMemory conforme necessário.

  2. Use a estrutura Aws::SDKOptions para configurar o uso do gerenciador de memória personalizado. Transmita a instância da estrutura para Aws::InitAPI. Antes de encerrar a aplicação, encerre o SDK chamando Aws::ShutdownAPI com a mesma instância.

    int main(void) { MyMemoryManager sdkMemoryManager; SDKOptions options; options.memoryManagementOptions.memoryManager = &sdkMemoryManager; Aws::InitAPI(options); // ... do stuff Aws::ShutdownAPI(options); return 0; }

STL, strings e vetores da AWS

Quando inicializado com um gerenciador de memória, o AWS SDK para C++ delega toda a alocação e a desalocação para o gerenciador de memória. Caso não exista um gerenciador de memória, o SDK usa new e delete globais.

Se você usar alocadores STL personalizados, deverá alterar as assinaturas de tipo de todos os objetos STL a serem comparados à política de alocação. Como a STL é amplamente usada na implementação e na interface do SDK, uma única abordagem no SDK inibiria a transmissão direta de objetos STL padrão para o SDK ou o controle da alocação de STL. Como alternativa, uma abordagem híbrida, que é utilizar alocadores personalizados internamente e permitir objetos STL padrão e personalizados na interface, poderia dificultar a investigação de problemas de memória.

A solução é usar a constante de tempo de compilação do sistema de memória USE_AWS_MEMORY_MANAGEMENT para controlar quais tipos de STL são utilizados pelo SDK.

Se a constante de tempo de compilação estiver habilitada (ativada), os tipos serão resolvidos para tipos STL com um alocador personalizado conectado ao sistema de memória da AWS.

Se a constante de tempo de compilação estiver desabilitada (desativada), todos os tipos Aws::* serão resolvidos para o tipo std::* padrão correspondente.

Exemplo de código do arquivo AWSAllocator.h no SDK

#ifdef USE_AWS_MEMORY_MANAGEMENT template< typename T > class AwsAllocator : public std::allocator< T > { ... definition of allocator that uses AWS memory system }; #else template< typename T > using Allocator = std::allocator<T>; #endif

No exemplo de código, o AwsAllocator pode ser um alocador personalizado ou padrão, dependendo da constante de tempo de compilação.

Exemplo de código do arquivo AWSVector.h no SDK

template<typename T> using Vector = std::vector<T, Aws::Allocator<T>>;

No exemplo de código, definimos os tipos Aws::*.

Se a constante de tempo de compilação estiver habilitada (ativada), o tipo será associado a um vetor usando a alocação de memória personalizada e o sistema de memória da AWS.

Se a constante de tempo de compilação estiver desabilitada (desativada), o tipo será associado a um std::vector normal com parâmetros de tipo padrão.

A criação de alias é usada para todos os tipos std:: no SDK que realizam alocação de memória, como contêineres, fluxos e buffers de strings. O AWS SDK para C++ usa esses tipos.

Problemas remanescentes

É possível controlar a alocação de memória no SDK; no entanto, os tipos STL ainda dominam a interface pública por meio de parâmetros de string para os métodos initialize e set do objeto de modelo. Se você não usa STL, mas utiliza strings e contêineres, precisa criar muitos temporários sempre que quer fazer uma chamada de serviço.

Para remover a maioria dos temporários e da alocação quando você faz chamadas de serviço usando não STL, implementamos o seguinte:

  • Toda função Init/Set que usa uma string tem uma sobrecarga que utiliza um const char*.

  • Toda função Init/Set que usa um contêiner (mapa/vetor) tem uma variante de adição que utiliza uma única entrada.

  • Toda função Init/Set que usa dados binários tem uma sobrecarga que utiliza um ponteiro para os dados e um valor length.

  • (Opcional) Toda função Init/Set que usa uma string tem uma sobrecarga que utiliza um const char* não terminado em zero e um valor length.

Desenvolvedores de SDK nativo e controles de memória

Siga estas regras no código do SDK:

  • Não use new e delete; em vez disso, use Aws::New<> e Aws::Delete<>.

  • Não use new[] e delete[]; use Aws::NewArray<> e Aws::DeleteArray<>.

  • Não use std::make_shared; useAws::MakeShared.

  • Use Aws::UniquePtr como ponteiros exclusivos para um único objeto. Use a função Aws::MakeUnique para criar o ponteiro exclusivo.

  • Use Aws::UniqueArray como ponteiros exclusivos para uma matriz de objetos. Use a função Aws::MakeUniqueArray para criar o ponteiro exclusivo.

  • Não use contêineres STL diretamente; use um dos typedefs Aws:: ou adicione um typedef para o contêiner desejado. Por exemplo:

    Aws::Map<Aws::String, Aws::String> m_kvPairs;
  • Use shared_ptr para qualquer ponteiro externo transmitido e gerenciado pelo SDK. É necessário inicializar o ponteiro compartilhado com uma política de destruição alinhada à forma como o objeto foi alocado. Você pode usar um ponteiro cru se não houver expectativa de que o SDK limpe o ponteiro.