You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两段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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:40:27