

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 中的内存管理 适用于 C\$1\$1 的 AWS SDK
<a name="memory-management"></a>

 适用于 C\$1\$1 的 AWS SDK 提供了一种控制库中内存分配和取消分配的方法。

**注意**  
仅当您使用通过已定义的编译时常量 `USE_AWS_MEMORY_MANAGEMENT` 构建的库版本时，自定义内存管理功能才可用。  
如果您使用的库版本是在没有这个编译时常量的情况下构建的，那么像 `InitializeAWSMemorySystem` 这样的全局内存系统函数将不会生效；而是会使用全局 `new` 和 `delete` 函数。

有关编译时常量的更多信息，请参见 [STL 和 AWS 字符串和](#stl-and-aws-strings-and-vectors)向量。

## 分配和取消分配内存
<a name="allocating-and-deallocating-memory"></a>

 **分配或取消分配内存** 

1. 子类 `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;
   };
   ```
**注意**  
您可以根据需要更改 `AllocateMemory` 的类型签名。

1. 使用 `Aws::SDKOptions` 结构来配置自定义内存管理器的用法。将该结构的实例传递到 `Aws::InitAPI`。在应用程序终止之前，必须对同一个实例调用 `Aws::ShutdownAPI` 来关闭 SDK。

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

## STL 和 AWS 字符串和向量
<a name="stl-and-aws-strings-and-vectors"></a>

使用内存管理器初始化时，会将所有分配和取消分配推 适用于 C\$1\$1 的 AWS SDK 迟到内存管理器。如果内存管理器不存在，SDK 将使用全局新建和删除。

如果您使用自定义 STL 分配器，则必须更改所有 STL 对象的类型签名以匹配分配策略。由于 SDK 的实现和接口中大量使用 STL，若 SDK 采用单一实现方式，将无法直接将默认 STL 对象传入 SDK，也无法对 STL 内存分配进行控制。另一种方案是混合实现方式 — 在内部使用自定义分配器，同时允许接口使用标准 STL 对象和自定义 STL 对象，但这种方式可能会增加内存问题的排查难度。

解决方案是使用内存系统的编译时常量 `USE_AWS_MEMORY_MANAGEMENT` 来控制 SDK 使用哪些 STL 类型。

如果启用编译时常量（开启），则使用连接到内存系统的自定义分配器将类型解析为 STL 类型。 AWS 

如果禁用编译时常量（设为关闭状态），则所有 `Aws::*` 类型都解析为相应的默认 `std::*` 类型。

 **来自 SDK 中 `AWSAllocator.h` 文件的示例代码** 

```
#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
```

在示例代码中，`AwsAllocator` 可以是自定义分配器或默认分配器，具体取决于编译时常量。

 **来自 SDK 中 `AWSVector.h` 文件的示例代码** 

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

在示例代码中，我们定义 `Aws::*` 类型。

如果启用了编译时常量（开启），则该类型将使用自定义内存分配和内存系统映射到向量。 AWS 

如果禁用编译时常量（设为关闭状态），则该类型将映射到带有默认类型参数的常规 `std::vector`。

类型别名用于 SDK 中执行内存分配的所有 `std::` 类型，例如容器、字符串流和字符串缓冲区。 适用于 C\$1\$1 的 AWS SDK 使用这些类型。

## 其余问题
<a name="remaining-issues"></a>

您可以控制该 SDK 中的内存分配；然而，STL 类型仍然在公共接口中占主导地位 — 通过模型对象的 `initialize` 和 `set` 方法中的字符串参数实现。如果您不使用 STL 而是使用字符串和容器，那么每当您想进行服务调用时，都必须创建很多临时变量。

为了删除使用非 STL 进行服务调用时的大部分临时变量和内存分配，我们实现了以下内容：
+ 每个接受字符串的 Init/Set 函数都有一个重载，该重载需要一个`const char*`.
+ 每个 Init/Set 使用容器（地图/向量）的函数都有一个添加变体，该变体需要一个条目。
+ 每个接受二进制数据的 Init/Set 函数都有一个重载，它需要一个指向数据的指针和一个`length`值。
+ （可选）每个接受字符串的 Init/Set 函数都有一个重载，该重载采用非零结尾`const char*`和一个`length`值。

## 原生 SDK 开发工具和内存控件
<a name="native-sdk-developers-and-memory-controls"></a>

在 SDK 代码中遵循以下规则：
+ 不要使用 `new` 和 `delete`；而是使用 `Aws::New<>` 和 `Aws::Delete<>`。
+ 不要使用 `new[]` 和 `delete[]`；而是使用 `Aws::NewArray<>` 和 `Aws::DeleteArray<>`。
+ 不要使用 `std::make_shared`；而是使用 `Aws::MakeShared`。
+ 使用 `Aws::UniquePtr` 表示指向单个对象的唯一指针。使用 `Aws::MakeUnique` 函数创建唯一指针。
+ 使用 `Aws::UniqueArray` 表示指向对象数组的唯一指针。使用 `Aws::MakeUniqueArray` 函数创建唯一指针。
+ 不要直接使用 STL 容器；使用其中一个 `Aws::` typedef 或者为所需的容器添加一个 typedef。例如：

  ```
  Aws::Map<Aws::String, Aws::String> m_kvPairs;
  ```
+ 使用 `shared_ptr` 表示传入 SDK 并由 SDK 管理的任何外部指针。必须使用与对象分配方式相匹配的销毁策略来初始化共享指针。如果 SDK 不应该清理指针，则您可以使用原始指针。