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

使用C语言read()解析/proc/meminfo获取错误内存值问题排查

解决/proc/meminfo读取MemTotal/MemFree数值异常的问题

我来帮你排查这个问题——你的代码里有几个关键逻辑漏洞导致了总内存数值异常偏大,咱们一步步拆解来看:

问题根源分析

你遇到的异常大数值(比如1575626486920),核心原因是解析变量没有在每次尝试读取字段前重置,加上手动逐字符匹配的边界处理不严谨:

  1. 变量累加未重置:totalbytes和freebytes在while循环外只初始化一次,如果程序多次触发字段解析逻辑(比如测试文件有重复的MemTotal行,或者跨Buffer的字段匹配失败),数值会在原有基础上持续累加,最终变得异常巨大。
  2. 跨Buffer匹配失效:手动逐字符匹配时,每次read后都会重置flag和匹配指针,一旦字段内容跨了两个Buffer块(比如MemTotal: 16384在第一个Buffer,256 kB在第二个),第二次读取时会重新从头匹配,导致之前的解析进度丢失,或者错误累加。
  3. 资源泄漏:原代码没有关闭文件描述符fd,会造成系统资源泄漏。

修正后的代码

我用更可靠的字符串查找和标准解析函数重构了代码,解决了上述问题:

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>

int main(int argc, char const *argv[]) {
    int fd = 0;
    ssize_t iRet = 0; // read返回值用ssize_t更严谨
    char Buffer[1024];
    memset(Buffer, '\0', sizeof(Buffer));
    
    const char *total_tag = "MemTotal:";
    const char *free_tag = "MemFree:";
    size_t total_len = strlen(total_tag);
    size_t free_len = strlen(free_tag);

    // 打开系统标准的/proc/meminfo文件
    fd = open("/proc/meminfo", O_RDONLY);
    if(fd == -1) {
        perror("Failed to open /proc/meminfo");
        return EXIT_FAILURE;
    }

    unsigned long total_mem = 0;
    long free_mem = 0;
    // 标记是否已找到目标字段,避免重复解析
    int found_total = 0;
    int found_free = 0;

    while((iRet = read(fd, Buffer, sizeof(Buffer)-1)) > 0) {
        Buffer[iRet] = '\0'; // 确保字符串以'\0'结尾,方便字符串操作
        char *ptr = Buffer;

        if(!found_total) {
            // 直接定位MemTotal字段位置
            char *total_pos = strstr(ptr, total_tag);
            if(total_pos != NULL) {
                // 跳过字段名和后续空白字符
                total_pos += total_len;
                while(*total_pos == ' ' || *total_pos == '\t') {
                    total_pos++;
                }
                // 用标准函数解析数字,避免手动累加错误
                total_mem = strtoul(total_pos, NULL, 10);
                found_total = 1;
            }
        }

        if(!found_free) {
            // 同理定位MemFree字段
            char *free_pos = strstr(ptr, free_tag);
            if(free_pos != NULL) {
                free_pos += free_len;
                while(*free_pos == ' ' || *free_pos == '\t') {
                    free_pos++;
                }
                free_mem = strtol(free_pos, NULL, 10);
                found_free = 1;
            }
        }

        // 两个字段都找到后提前退出循环,提高效率
        if(found_total && found_free) {
            break;
        }
    }

    // 输出解析结果
    if(found_total && found_free) {
        printf("Total Memory in KB : %lu\n", total_mem);
        printf("Free Memory in KB : %ld\n", free_mem);
        double used_percent = ((total_mem - free_mem) * 100.0) / total_mem;
        printf("Percentage Used : %.0f%%\n", used_percent);
    } else {
        printf("Failed to extract MemTotal or MemFree information\n");
    }

    close(fd); // 务必关闭文件描述符
    return EXIT_SUCCESS;
}

关键修改说明

  1. 用strstr替代手动匹配:直接定位字段位置,避免逐字符匹配的边界错误,逻辑更清晰。
  2. 标准数字解析函数:用strtoul/strtol替代手动累加数字,彻底解决数值异常累加的问题。
  3. 字段匹配标记:用found_total和found_free确保每个字段只解析一次,避免重复累加。
  4. 提前退出逻辑:找到目标字段后立即终止循环,无需读取剩余内容,提升效率。
  5. 完善错误处理:添加文件打开失败的错误提示,以及字段解析失败的友好提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 12:27:33