两段C++代码内存占用相同的原因及内存统计、const char*优化问询
问题解析与解决方案
核心疑问
- 为什么两段存入不同长度字符串字面量指针的代码,进程内存占用都约11MB?是不是只统计了指针的大小?
- 如何从外部准确统计软件的内存占用?
- 原本以为每次
push_back字符串字面量会创建新字符串,现在用new std::string实现了多份字符串的需求,但想找不用std::string、仅用const char*的优雅实现方式。
第一段代码(长字符串字面量)
#include <vector> int main() { const int iterations = 1'000'000; std::vector<const char *> c; for (int i = 0; i < iterations; i++) { c.push_back("qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiop"); } }
第二段代码(短字符串字面量)
#include <vector> int main() { const int iterations = 1'000'000; std::vector<const char *> c; for (int i = 0; i < iterations; i++) { c.push_back("qwerty"); } }
修改后的代码(用new std::string实现多份字符串)
#include <vector> int main() { const int iterations = 1'000'000; std::vector<const char *> c; for (int i = 0; i < iterations; i++) { std::string* s = new std::string("sadadasd"); c.push_back((*s).c_str()); } }
问题解答
1. 内存占用相同的原因
字符串字面量是**编译期就存入程序只读数据段(.rodata)**的常量,整个程序里相同的字符串字面量只会存一份。不管循环多少次push_back,vector里存的都是同一个指针的副本,指向只读段里那唯一的一份字符串。
64位系统下,一个指针占8字节,100万个指针就是1e6 * 8 = 8e6字节(约7.6MB),加上vector本身的内存开销和进程的基础内存,总占用约11MB——这和字符串字面量的长度无关,因为字符串本体只存了一份,vector里只有指针。
2. 外部准确统计内存的方法
要准确统计软件内存,需要区分不同的内存指标:
- 虚拟内存(VSZ):进程申请的全部虚拟地址空间大小,包含未实际分配的部分。
- 常驻内存(RSS):进程实际占用的物理内存大小,不含交换出去的部分。
- 堆内存:进程在堆上分配的内存(比如
new出来的内存)。
Linux下可以用top、ps aux查看VSZ和RSS,用valgrind --tool=massif分析堆内存分配细节;Windows下可以用任务管理器“详细信息”里的“内存(专用工作集)”,或者VMMap工具查看更细粒度的内存分布。
3. 不用std::string、仅用const char*实现多份字符串的方式
要让每个指针指向不同的字符串副本,需要手动在堆上分配内存并复制字符串内容:
实现代码
#include <vector> #include <cstring> int main() { const int iterations = 1'000'000; const char* src = "sadadasd"; const size_t str_len = strlen(src) + 1; // 加1是为了存终止符'\0' std::vector<const char*> c; c.reserve(iterations); // 预分配空间,避免vector多次扩容 for (int i = 0; i < iterations; i++) { char* buf = new char[str_len]; // 在堆上分配对应大小的内存 strcpy(buf, src); // 复制字符串内容到堆内存 c.push_back(buf); // 存入指针 } // 必须手动释放堆内存,避免内存泄漏 for (const char* ptr : c) { delete[] ptr; } }
说明
- 用
new char[str_len]为每个字符串单独分配堆内存,每个指针指向独立的内存块,内存占用会随字符串长度和循环次数增加。 - 最后要遍历vector,用
delete[]释放每个指针指向的内存,否则会造成内存泄漏。 - 调用
c.reserve(iterations)预分配vector空间,减少扩容带来的额外内存开销和性能损耗。
内容的提问来源于stack exchange,提问作者Ceccoclat
相关产品推荐
相关产品推荐

