STD中的动态内存分配
经常使用微控制器和 C++,知道我不执行动态内存分配对我来说很重要。但是,我想充分利用 STD 库。确定 STD 中的函数/类是否使用动态内存分配的最佳策略是什么?
到目前为止,我想出了这些选项:
- 阅读并理解 STD 代码。这当然是可能的,但老实说,这不是最容易阅读的代码,而且代码很多。
- 阅读代码的一种变体可能是让脚本搜索内存分配并突出显示这些部分以使其更易于阅读。这仍然需要弄清楚在哪里使用分配内存的函数,等等。
- 只是测试我想使用的内容并使用调试器观察内存。到目前为止,我一直在使用这种方法,但这是一种反应式方法。我想在设计代码时事先知道我可以从 STD 中使用什么。还有什么可以说在某些(边缘)情况下分配了内存。这些可能不会出现在这个有限的测试中。
- 最后,可以做的是定期扫描生成的汇编代码以进行内存分配。我怀疑这可以编写脚本并包含在工具链中,但这又是一种反应式方法。
如果您看到任何其他选项或有做类似事情的经验,请告诉我。
ps 目前我主要使用 ARM Cortex-Mx 芯片使用 GCC 进行编译。
回答
你在评论中有一些很好的建议,但没有实际答案,所以我会尝试一个答案。
从本质上讲,您暗示 C 和 C++ 之间存在一些并不真正存在的差异。你怎么知道 stdlib 函数不分配内存?
一些 STL 函数被允许分配内存,它们应该使用分配器。例如,向量采用模板参数作为替代分配器(例如池分配器很常见)。甚至有一个标准函数来发现一个类型是否使用内存
但是......像 std::function 这样的一些类型有时使用内存分配,有时不使用,这取决于参数类型的大小,所以你的偏执并非完全没有道理。
C++ 通过新建/删除分配。通过 malloc/free 新建/删除分配。
所以真正的问题是,你能覆盖 malloc/free 吗?答案是肯定的,请参阅此答案/sf/answers/852119831/。通过这种方式,您可以跟踪所有分配,并在运行时捕获错误,这还不错。
如果你真的很铁杆,你可以做得更好。您可以编辑标准的“运行时 C 库”以将 malloc/free 重命名为其他名称。这可以通过作为 gcc 工具链一部分的“objcopy”来实现。重命名 malloc/free 后,比如 ma11oc/fr33,任何对分配/释放内存的调用将不再链接。将带有“-nostdlib”和“-nodefaultlibs”选项的可执行文件链接到gcc,而是链接您自己的一组库,这些库是您使用objcopy 生成的。
老实说,我只见过一次成功完成此操作,并且您不信任 objcopy 的程序员,因此他只是使用二进制编辑器手动找到标签“malloc”“free”,并对其进行更改。不过它绝对有效。
编辑:正如 Fureeish 所指出的(见评论),C++ 标准不保证 new/delete 使用 C 分配器函数。但是,这是一个非常常见的实现,您的问题确实特别提到了 GCC。在 30 年的开发中,我从未见过一个 C++ 程序运行两个堆(一个用于 C,一个用于 C++)仅仅因为标准允许它。它根本没有任何优势。不过,这并不排除未来可能存在优势的可能性。
为了清楚起见,我的回答假设有新用途malloc 分配内存。这并不意味着您可以假设每个新调用都调用 malloc,因为可能涉及缓存,并且操作符 new 可能会过载以使用全局级别的任何内容。请参阅此处了解 GCC/C++ 分配器方案。
https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html
另一个编辑:
如果你想获得技术 - 这取决于你使用的 libstdc++ 版本。您可以在 new_op.cc 中找到 operator new,在(我假设是官方的)源存储库中
(我现在就停下来)