Administración de la memoria en el AWS SDK para C++ - AWS SDK para C++

Administración de la memoria en el AWS SDK para C++

El AWS SDK para C++ ofrece una manera de controlar la asignación y desasignación de memoria en una biblioteca.

nota

La administración de memoria personalizada solo está disponible si utiliza una versión de la biblioteca creada con la constante de tiempo de compilación definida USE_AWS_MEMORY_MANAGEMENT.

Si utiliza una versión de la biblioteca creada sin la constante de tiempo de compilación, las funciones del sistema de memoria global, como InitializeAWSMemorySystem, no funcionarán; en su lugar, se utilizarán las funciones globales new y delete.

Para obtener más información sobre la constante de tiempo de compilación, consulte STL y cadenas y vectores de AWS.

Asignación y desasignación de memoria

Para asignar o desasignar memoria

  1. SubclaseMemorySystemInterface: 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

    Puede cambiar la firma de tipo de AllocateMemory si es necesario.

  2. Utilice la estructura Aws::SDKOptions para configurar el uso del administrador de memoria personalizado. Transfiera la instancia de la estructura a Aws::InitAPI. Antes de que la aplicación finalice, se debe cerrar el SDK llamando a Aws::ShutdownAPI con la misma instancia.

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

STL y cadenas y vectores de AWS

Cuando se inicializa con un administrador de memoria, el AWS SDK para C++ desvía todas las asignaciones y desasignaciones al administrador de memoria. Si no existe un administrador de memoria, el SDK usa global new y delete.

Si utiliza asignadores STL personalizados, debe modificar las firmas de tipos de todos los objetos STL para que coincidan con la política de asignación. Como el STL ocupa un lugar destacado en la implementación y la interfaz del SDK, un enfoque único en el SDK impediría la transferencia directa de los objetos STL predeterminados al SDK o el control de la asignación de STL. El uso de una alternativa, como un enfoque híbrido (utilizar asignadores personalizados internamente y permitir la presencia de objetos STL estándares y personalizados en la interfaz), podría dificultar la investigación de los problemas de memoria.

La solución consiste en utilizar la constante de tiempo de compilación USE_AWS_MEMORY_MANAGEMENT del sistema de memoria para controlar los tipos de STL que utiliza el SDK.

Si la constante de tiempo de compilación está habilitada (on), los tipos se convierten en tipos STL con un asignador personalizado conectado al sistema de memoria de AWS.

Si la constante de tiempo de compilación está deshabilitada (off), todos los tipos Aws::* se resuelven con el tipo std::* predeterminado correspondiente.

Código de ejemplo del archivo AWSAllocator.h del 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

En el código de ejemplo, AwsAllocator puede ser un asignador personalizado o un asignador predeterminado, en función de la constante de tiempo de compilación.

Código de ejemplo del archivo AWSVector.h del SDK

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

En el código de ejemplo, definimos los tipos Aws::*.

Si la constante de tiempo de compilación está habilitada (on), el tipo se asigna a un vector mediante la asignación de memoria personalizada y el sistema de memoria de AWS.

Si la constante de tiempo de compilación está desactivada (off), el tipo se asigna a un std::vector normal con los parámetros de tipo predeterminados.

El alias de tipos se usa con todos los tipos std:: del SDK que realizan la asignación de memoria; por ejemplo, los contenedores, los flujos de cadenas y los búferes de cadenas. El AWS SDK para C++ utiliza estos tipos.

Problemas pendientes

Puede controlar la asignación de memoria en el SDK; sin embargo, los tipos de STL siguen dominando la interfaz pública a través de los parámetros initialize del objeto y los métodos set del modelo. Si no utiliza STL y usa cadenas y contenedores en su lugar, tendrá que crear muchos archivos temporales cada vez que desee realizar una llamada de servicio.

Para eliminar la mayoría de los archivos temporales y la asignación al realizar llamadas de servicio que no utilizan STL, hemos implementado lo siguiente:

  • Cada función Init/Set que toma una cadena tiene una sobrecarga que requiere un const char*.

  • Cada función Init/Set que toma un contenedor (mapa/vector) tiene una variante de adición que usa una sola entrada.

  • Cada función Init/Set que toma datos binarios tiene una sobrecarga que dirige un puntero a los datos y a un valor length.

  • (Opcional) Cada función Init/Set que toma una cadena tiene una sobrecarga que toma un valor const char* con una terminación distinta de cero y un length

Desarrolladores de SDK nativos y controles de memoria

En el código del SDK, siga estas reglas:

  • No use new ydelete; utilice Aws::New<> y Aws::Delete<> en su lugar.

  • No use new[] ydelete[]; utilice Aws::NewArray<> y Aws::DeleteArray<>.

  • No usestd::make_shared; utilice Aws::MakeShared.

  • Utilice Aws::UniquePtr para tener punteros únicos a un solo objeto. Utilice la función Aws::MakeUnique para crear el puntero único.

  • Utilice Aws::UniqueArray para tener punteros únicos a una matriz de objetos. Utilice la función Aws::MakeUniqueArray para crear el puntero único.

  • No utilice contenedores STL directamente; use uno de los typedefs de Aws:: o añada un typedef para el contenedor que desee. Por ejemplo:

    Aws::Map<Aws::String, Aws::String> m_kvPairs;
  • Utilice shared_ptr con cualquier puntero externo transferido al SDK y administrado por él. Debe inicializar el puntero compartido con una política de destrucción que coincida con la manera en la que se asignó el objeto. Puede usar un puntero sin procesar si no se espera que el SDK limpie el puntero.