【问题标题】:c++ on low memory systems. Standard libs are using all the memory!c++ 在低内存系统上。标准库正在使用所有内存!
【发布时间】:2023-03-12 12:13:02
【问题描述】:

我需要尽可能多地削减内存。我正在使用带有 STL 的标准 C++。该程序没有做太多(还),它仍然需要 960Kb [根据top]!可执行文件大小只有 64KB。

代码有 3000 行长,我不打算发布。我相信问题不在于我的代码,而在于系统库。

单个 main() 函数(包括我的所有代码但不使用它)使用 732Kb 的 RAM
简单代码:

int main() {
sleep(1000); //do nothing
return 0;
}
//Uses 732kb of RAM

我的代码没有全局变量(除了对我隐藏的库中的变量)。

我正在使用标准库:libstdc++ (STL)、GNU libc。还有一个 BSD 套接字和 libev 以及非标准 STL 绳索类。

我可以运行一些内存分析器吗?

平台:Linux 2.6.18-32,32 位处理器,16MB 总系统 RAM,无可用交换
编译器:GCC 4
标准库:GCC 的 libstdc++
编译器选项:-Os(无调试符号)

没有大量使用模板:容器和迭代器就是这样。但是我正在大量使用 SGI STL 绳索类。

测试环境是运行 Linux 的基本服务器,具有 128MB RAM、Pentium III 667 Mhz、CentOS 5.5,无仿真。

更新:我想知道库本身(代码大小)是否会导致问题。共享库不需要加载到 RAM 中吗?

【问题讨论】:

  • 没有任何代码,几乎不可能告诉你从哪里开始。
  • 没有代码,没有好的帮助。请贴出代码(你说这是一个非常基本的 C++ 程序)。
  • 程序在做什么(或应该做什么)?
  • @nightcrack,它是一个 HTTP 透明代理,可用 3MB 内存运行。
  • 您使用的是哪个标准库和编译器?您正在构建调试或发布二进制文件吗?你在剥离符号吗?您是否使用大量不同的模板参数来实例化 STL 模板?

标签: c++ stl embedded low-memory


【解决方案1】:

开始剥离功能,直到内存使用量下降。先走极端——如果你可以用sleep(1000);替换main并且你的内存使用率仍然很高,请查看代码和静态数据——在全局范围内初始化的任何内容或类或函数内的静态,以及模板实例化不同的类型和调试符号。

更新:删除了关于 STL 分配器的错误评论。它可能适用于其他编译器/STL 版本(如果您想查看历史记录,请查看),但不适用于此问题。

请注意,malloc/operator new 通常会吝啬将空闲内存还给操作系统,这将导致您的程序作为一个整体不会随着时间的推移而缩减其明显的使用量;该内存将通过未来的分配在整个程序中重复使用,因此除了将“内存使用”数字无限期地保持在或接近其高水位线之外,这通常不是一个大问题。

【讨论】:

  • 试过main() sleep(1000) RAM使用量还是732kb!
  • 在这种情况下,您正在查看代码大小(是的,包括您的程序链接到的所有共享库)和静态数据。请注意,对于大多数操作系统来说,共享库的加载对于所有使用它的进程只会在 RAM 中加载一次;这可能会使内存使用数字有点欺骗性,但如果您的程序就是您运行所需的全部,它可能对您没有多大帮助。如果你可以设置静态链接,它实际上可能会节省你的内存,因为我相信可以告诉链接器丢弃你的程序不从库中使用的符号。
  • GCC 的 libstdc++ The current default choice for allocator is __gnu_cxx::new_allocator 似乎不是这种情况,它在每次分配后通过调用 newdelete gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt04ch11.html 来释放内存
  • @unixman83 好电话!我最近读过这个,但对于手头的问题来说似乎是不正确的。更新我的答案。
【解决方案2】:

更新:我想知道如果 库本身(代码大小)是 导致问题。不共享 库需要加载到 内存?

宾果游戏。至少在 Mac OS X 上,Top 在物理内存使用中包含共享库的大小。当然,每个库只有一个副本驻留在内存中。

查看top 的文档以获取解决方法,或者直接放弃它并使用malloc_info()。不过,要小心找到一种方法来说明代码、堆栈和全局使用情况。

【讨论】:

  • @unix:不,共享库每个进程只需要加载一次。库的全局变量会重复,但这并不是为您增加 700k+ 的原因。静态链接将强制为您的进程单独加载代码,从而导致更糟糕的使用——这将如何解决任何问题?
  • 重申一下,相同的代码被多次计算。您应该能够创建一千个新进程并验证top 报告的使用情况是否超过了系统中的物理内存,而且虚拟内存也不存在。
【解决方案3】:

让链接器发出一个链接映射文件;您可以使用它来准确确定您的代码需要多少静态链接代码和静态数据空间。

堆栈、堆空间和共享库是附加的,并在运行时分配。

如果您有 16Mb 的 RAM,这真的很重要吗?可能存在相对较大但固定的开销,并且您的整体内存占用不会随着添加的代码行线性增长。

【讨论】:

  • 加上 Linux 内核的 RAM 开销和网络缓冲,我在重负载下真的只有 1.5MB 左右。
  • @unix:是的,我可以说很多关于 Linux 对嵌入式系统的适用性,这将引发另一个完整的讨论;)。不过你很幸运;我目前的项目有 64K 总 RAM,200K 从 Flash 运行的代码,包括一个 RTOS、文件系统、USB、CAN 总线、两个串行端口、VHF 收发器和 13 个应用程序线程,我目前有大约 4Kb 剩余内存。所以 1.5Mb 在我看来是奢侈的挥霍!
【解决方案4】:

由于目标是 linux,我认为您可以通过查看 /proc/{pid_number} 中的 maps 和 smaps 文件来了解有关内存使用的详细信息,尤其是共享库组件

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    相关资源
    最近更新 更多