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

Linux下C++程序中获取abc.exe最大内存占用并存储至变量

问题

我希望测量abc.exe在gen.exe生成的随机测试用例下的最大内存占用。当前已编写如下C++代码,用于循环调用gen.exe生成测试用例test.in,再调用abc.exe处理该测试用例:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int i = 0;
    while (true)
    {
        string si = to_string(i);
        cout << i << "\n";
        if (system(("echo " + si + "| ./gen.exe > test.in").c_str())) // gen.exe 是测试用例生成器
        {
            cout << "gen error\n";
            break;
        }
        if (system(("./abc.exe < test.in > a.out").c_str())) // abc.exe 是待测试程序
        {
            cout << "abc error\n";
            break;
        }
        i++;
    }
}

我知道可以使用time -v ./abc.exe查看内存使用情况,但该结果仅输出到终端,无法保存到变量中,请问该如何实现?

解决方案

方法1:重定向time输出到文件或变量

time -v的输出默认走标准错误(stderr),不是标准输出(stdout),直接用>重定向不会生效,得把stderr也重定向。

保存到文件

修改调用abc.exe的命令,把内存日志存到单独文件里:

if (system(("time -v ./abc.exe < test.in > a.out 2> mem_log_" + si + ".txt").c_str()))

每个测试用例的内存数据会存在mem_log_0.txt、mem_log_1.txt这类文件里,之后从中提取Maximum resident set size(最大驻留内存)的值就行。

捕获输出到C++变量

要是想直接把内存数据读到程序变量里,用popen代替system,读取time -v的输出:

// 替换原来调用abc.exe的system代码段
FILE* pipe = popen(("time -v ./abc.exe < test.in > a.out 2>&1").c_str(), "r");
if (!pipe) {
    cout << "abc error\n";
    break;
}
char buffer[1024];
string mem_output;
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
    mem_output += buffer;
}
int status = pclose(pipe);
if (status != 0) {
    cout << "abc error\n";
    break;
}
// 解析最大内存值
size_t pos = mem_output.find("Maximum resident set size");
if (pos != string::npos) {
    pos = mem_output.find(":", pos);
    string mem_str = mem_output.substr(pos + 1);
    // 去掉空格和换行符
    mem_str.erase(remove_if(mem_str.begin(), mem_str.end(), ::isspace), mem_str.end());
    long long max_mem = stoll(mem_str);
    cout << "测试用例 " << i << " 最大内存占用: " << max_mem << " KB\n";
    // 可以把max_mem存入数组或文件,方便后续统计最大值
}

这里2>&1是把stderr重定向到stdout,让popen能读到time -v的输出,再解析出需要的内存字段。

方法2:用getrusage系统调用直接获取

不想依赖time命令的话,用fork+exec启动abc.exe,再用getrusage获取子进程的资源使用情况,这种方法更直接:

#include <sys/wait.h>
#include <sys/resource.h>

// 替换原来调用abc.exe的system代码段
pid_t pid = fork();
if (pid == -1) {
    perror("fork失败");
    break;
} else if (pid == 0) {
    // 子进程执行abc.exe
    freopen("test.in", "r", stdin);
    freopen("a.out", "w", stdout);
    execl("./abc.exe", "./abc.exe", nullptr);
    perror("exec失败");
    exit(1);
} else {
    // 父进程等待子进程结束并读取资源数据
    int status;
    waitpid(pid, &status, 0);
    if (WEXITSTATUS(status) != 0) {
        cout << "abc error\n";
        break;
    }
    struct rusage usage;
    getrusage(RUSAGE_CHILDREN, &usage);
    long long max_mem = usage.ru_maxrss; // Linux下单位是KB,macOS下是字节
    cout << "测试用例 " << i << " 最大内存占用: " << max_mem << " KB\n";
}

这种方式不用解析字符串,也不依赖外部命令,适合集成到C++程序里。注意ru_maxrss的单位在不同系统有差异,需要根据环境调整。

方法3:用ps实时监控(适合调试)

要是需要实时看abc.exe的内存变化,可以用ps命令循环读取,但精度不如前两种,适合临时调试:

// 后台启动abc.exe
system("./abc.exe < test.in > a.out &");
// 需要获取abc.exe的PID,这里可以用pidof或者其他方式,示例中假设已经拿到pid
pid_t pid = ...; 
long long max_mem = 0;
string cmd = "ps -o rss= -p " + to_string(pid);
FILE* pipe = popen(cmd.c_str(), "r");
char buffer[64];
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
    long long current = stoll(buffer);
    if (current > max_mem) max_mem = current;
    usleep(10000); // 每10毫秒检查一次
}
pclose(pipe);
cout << "最大内存占用: " << max_mem << " KB\n";

这种方法需要处理进程后台运行和PID获取,复杂度较高,一般优先用前两种方法。

内容的提问来源于stack exchange,提问作者Darkolin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:25:16