使用C语言read()解析/proc/meminfo获取错误内存值问题排查
解决/proc/meminfo读取MemTotal/MemFree数值异常的问题
我来帮你排查这个问题——你的代码里有几个关键逻辑漏洞导致了总内存数值异常偏大,咱们一步步拆解来看:
问题根源分析
你遇到的异常大数值(比如1575626486920),核心原因是解析变量没有在每次尝试读取字段前重置,加上手动逐字符匹配的边界处理不严谨:
- 变量累加未重置:
totalbytes和freebytes在while循环外只初始化一次,如果程序多次触发字段解析逻辑(比如测试文件有重复的MemTotal行,或者跨Buffer的字段匹配失败),数值会在原有基础上持续累加,最终变得异常巨大。 - 跨Buffer匹配失效:手动逐字符匹配时,每次
read后都会重置flag和匹配指针,一旦字段内容跨了两个Buffer块(比如MemTotal: 16384在第一个Buffer,256 kB在第二个),第二次读取时会重新从头匹配,导致之前的解析进度丢失,或者错误累加。 - 资源泄漏:原代码没有关闭文件描述符
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; }
关键修改说明
- 用
strstr替代手动匹配:直接定位字段位置,避免逐字符匹配的边界错误,逻辑更清晰。 - 标准数字解析函数:用
strtoul/strtol替代手动累加数字,彻底解决数值异常累加的问题。 - 字段匹配标记:用
found_total和found_free确保每个字段只解析一次,避免重复累加。 - 提前退出逻辑:找到目标字段后立即终止循环,无需读取剩余内容,提升效率。
- 完善错误处理:添加文件打开失败的错误提示,以及字段解析失败的友好提示。
内容的提问来源于stack exchange,提问作者Prasad Wable
相关产品推荐
相关产品推荐

