为什么要对堆栈中的内存使用自定义动态内存分配?
Why use custom dynamic memory allocation over memory from stack?
上下文:我正在做一个项目,客户需要我们使用自定义动态内存分配,而不是从堆栈中分配对象。请注意,有问题的对象在编译期间具有已知的大小,甚至不需要动态分配。这让我很纳闷,
在哪些上下文中,对象的自定义动态内存分配可能比从堆栈中分配对象更好?(在编译过程中已知大小)
举个例子。如果Dog
是一个类,那么他们希望我们做的不仅仅是声明Dog puppy;
Dog* puppy = nullptr;
custom_alloc(puppy);
new(puppy) Dog(); // the constructor
// do stuff
puppy->~Dog(); // the destructor
custom_free(puppy)
我们不知道真正的custom_alloc
函数。为了使程序运行,给定的custom_alloc
函数将是malloc
的包装器。custom_free
将是free
的包装
我不喜欢这种方法,并且想知道这何时真正有用,或者他们真正想通过这样做来解决什么。
可能的原因:
堆栈大小是有限的;虽然典型的线程库为每个线程的堆栈分配 1-10 MB,但对于预计同时启动数百或数千个线程的应用程序(例如高流量 Web 服务器;Microsoft IIS 过去使用 256 KB 的限制,并且仅在 64 位设置中将其增加到 512 KB)。
您可能希望在函数返回后保留一个对象(不使用全局变量)。虽然 NRVO 和/或移动语义确实意味着按值返回对象通常相对便宜,但当 NRVO 不适用时,复制单个指针比其他任何东西都便宜。
审核/跟踪:他们可能希望对特定类型使用自定义函数来跟踪内存分配模式
持久存储:分配器可能由内存映射文件支持;对于结构化数据,该文件可能兼作长期存储
性能:已知自定义分配器(例如英特尔的 TBB)在某些情况下会显著缩短运行时间。这更像是使用自定义分配器而不是默认分配器的理由;自定义分配器通常不会击败堆栈存储(除非在非常小众的情况下,可以通过从堆栈中删除大型对象并将它们放在自己的专用存储中来改善内存局部性)。
(可能是一个糟糕的主意)避免异常处理清理开销。如果您的类是 RAII,则必须生成代码以在发生异常时沿各种代码路径清理它们。原始指针不会生成任何此类代码。当然,如果您不采取措施自己执行异常清理,这意味着内存泄漏,但在极少数情况下(例如,当您期望程序完全退出时,并且您希望操作系统处理内存清理时),这可能会提供一个小的"好处"。
上述组合:他们可能希望能够通过链接不同的运行时库来提供
custom_alloc
综上所述,他们这样做的方法非常糟糕;需要手动放置new
和析构函数调用是不愉快的(std::unique_ptr
/std::shared_ptr
可以通过提供自定义删除器函子来帮助您完成这项工作,但即使如此也很丑陋)。通常,如果您需要自定义分配器,则需要为operator new
/operator delete
定义适当的重载。这样,避免堆栈分配(无论出于何种原因)就不会那么令人不快;您只需将逻辑堆栈分配的变量替换为std::unique_ptr
s(通过std::make_unique
创建),您的代码仍然相当简单。
- 使用模板类的自定义列表类型中的内存泄漏
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 自己的自定义向量类. 内存重新分配
- 自定义内存管理器在发布模式下工作正常,但在调试模式下则不然
- shared_ptr的删除程序是否存储在自定义分配器分配的内存中?
- 自定义哈希表实现-将字符串映射到整数时出现内存错误
- 结构向量中自定义结构函数的内存使用
- 适用于 std::unique_ptr 的内存高效自定义删除器?
- 为什么要对堆栈中的内存使用自定义动态内存分配?
- 如何专用/分配自定义内存位置,以便可以在C 中编辑该位置
- 自定义内存分配器示例(需要一些说明)
- std::vector 如何支持未知大小的自定义对象的连续内存
- C 发布的矢量包含自定义类的内存
- 跨共享/静态库集成C++自定义内存分配器
- 如何在 C++ 中安全地为 char *array 重新分配内存(它适用于自定义字符串类)
- 自定义链表C++中的内存泄漏
- 如何将sf::Font复制到自定义池分配的内存中
- 带有realloc的自定义池内存分配器
- 如何为共享内存转发声明自定义unique_ptr
- 自定义内存分配和多个继承类的解除分配