如何在C++中精准限制程序的内存使用上限

来源:站长联盟作者:IT柏拉图头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何在C++中精准限制程序的内存使用上限》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何在C++中精准限制程序的内存使用上限》有用,将其分享出去将是对创作者最好的鼓励。

在C++程序开发中,合理限制内存使用上限能够避免程序异常占用过多系统资源,提升整体运行的稳定性。无论是服务端程序还是嵌入式场景下的应用,精准控制内存都是资源管理的核心需求之一。

如何在C++中精准限制程序的内存使用上限

系统层面限制:使用setrlimit函数

在类Unix系统中,可以通过setrlimit系统调用设置进程的资源限制,其中RLIMIT_AS参数可以限制进程的最大虚拟内存使用量,这是最直接限制程序内存上限的方式。

该方式的作用范围是整个进程,不需要修改程序的内存申请逻辑,适合快速为已有程序添加内存限制。

代码示例

#include <sys/resource.h>
#include <iostream>
#include <cstdlib>

int main() {
    // 定义资源限制结构体
    struct rlimit mem_limit;
    // 设置最大虚拟内存为100MB,单位字节
    mem_limit.rlim_cur = 100 * 1024 * 1024;
    mem_limit.rlim_max = 100 * 1024 * 1024;
    
    // 设置RLIMIT_AS限制,如果失败输出错误信息
    if (setrlimit(RLIMIT_AS, &mem_limit) != 0) {
        std::cerr << "设置内存限制失败" << std::endl;
        return 1;
    }
    
    // 尝试申请超过限制的内存,会触发bad_alloc异常
    try {
        // 申请200MB内存,超过设置的100MB限制
        char* big_mem = new char[200 * 1024 * 1024];
        delete[] big_mem;
    } catch (const std::bad_alloc& e) {
        std::cerr << "内存申请失败,超过限制: " << e.what() << std::endl;
    }
    
    return 0;
}

注意事项

  • RLIMIT_AS限制的是虚拟内存总量,包含堆、栈、共享内存等所有虚拟地址空间的使用
  • 设置的限制对该进程以及后续创建的子进程都生效
  • Windows系统没有setrlimit接口,需要使用Windows API的SetProcessWorkingSetSize或者作业对象(Job Object)实现类似功能

代码层面限制:自定义内存分配器

如果需要在更细的粒度上控制内存使用,比如只限制某个模块或者某类对象的内存申请,可以自定义内存分配器,在申请内存时校验当前已使用内存是否超过上限。

实现思路

自定义分配器需要重载operator newoperator delete,维护一个全局的内存使用计数器,每次申请内存时累加计数器,释放时减少计数器,当申请的内存会导致计数器超过上限时抛出异常。

代码示例

#include <iostream>
#include <cstdlib>
#include <mutex>

// 全局内存使用计数器,单位字节
static size_t g_used_memory = 0;
// 内存上限,设置为50MB
static const size_t MEMORY_LIMIT = 50 * 1024 * 1024;
// 互斥锁保证多线程下计数器操作安全
static std::mutex g_mem_mutex;

// 重载全局operator new
void* operator new(size_t size) {
    std::lock_guard<std::mutex> lock(g_mem_mutex);
    // 检查申请后的总内存是否超过上限
    if (g_used_memory + size > MEMORY_LIMIT) {
        throw std::bad_alloc();
    }
    // 申请内存
    void* ptr = malloc(size);
    if (!ptr) {
        throw std::bad_alloc();
    }
    // 更新计数器
    g_used_memory += size;
    return ptr;
}

// 重载全局operator delete
void operator delete(void* ptr, size_t size) noexcept {
    if (!ptr) return;
    std::lock_guard<std::mutex> lock(g_mem_mutex);
    free(ptr);
    // 更新计数器
    g_used_memory -= size;
}

int main() {
    try {
        // 第一次申请30MB内存
        char* mem1 = new char[30 * 1024 * 1024];
        std::cout << "第一次申请内存成功" << std::endl;
        
        // 第二次申请30MB内存,总使用60MB超过50MB上限
        char* mem2 = new char[30 * 1024 * 1024];
        delete[] mem2;
        delete[] mem1;
    } catch (const std::bad_alloc& e) {
        std::cerr << "内存申请失败,超过自定义上限: " << e.what() << std::endl;
    }
    
    return 0;
}

注意事项

  • 该方式只拦截通过new申请的内存,如果是用malloc或者第三方库的内存申请接口,需要额外适配
  • 多线程场景下必须使用互斥锁保证计数器操作的原子性,避免计数错误
  • 如果程序中存在内存泄漏,计数器只会递增不会递减,会提前触发限制

两种方式的对比

可以根据实际场景选择合适的内存限制方式,以下是两种方式的特性对比:

限制方式作用范围实现难度跨平台性粒度控制
setrlimit系统调用整个进程类Unix系统原生支持粗粒度
自定义内存分配器可自定义范围可跨平台实现细粒度

补充:内存使用监控

除了直接限制内存上限,还可以在程序中定期监控内存使用情况,当接近上限时主动释放非必要资源或者输出告警日志,这种方式相对柔性,不会直接终止内存申请操作。

可以通过读取/proc/self/status文件(类Unix系统)或者调用系统API获取当前进程的内存使用量,再和预设的阈值做对比。

#include <iostream>
#include <fstream>
#include <string>

// 获取当前进程虚拟内存使用量,单位KB
size_t get_vm_usage() {
    std::ifstream status_file("/proc/self/status");
    std::string line;
    while (std::getline(status_file, line)) {
        if (line.find("VmSize:") == 0) {
            // 格式为 VmSize:   12345 kB
            size_t pos = line.find_first_of("0123456789");
            if (pos != std::string::npos) {
                return std::stoi(line.substr(pos));
            }
        }
    }
    return 0;
}

int main() {
    size_t vm_usage = get_vm_usage();
    std::cout << "当前进程虚拟内存使用量: " << vm_usage << " KB" << std::endl;
    // 假设阈值为102400KB(100MB),超过则输出告警
    if (vm_usage > 102400) {
        std::cerr << "内存使用接近上限,请注意释放资源" << std::endl;
    }
    return 0;
}

C++memory_limitresource_controlsetrlimit修改时间:2026-07-20 19:33:16

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。