后台运行程序比较cJSON对象时出现内存泄漏,寻求解决方法
内存泄漏问题分析与修复
泄漏原因
你的代码存在两处核心内存泄漏/野指针问题:
- 未释放旧的
prev/current对象:每次更新prev或current时,原来的对象没有调用cJSON_Delete释放,导致内存持续累积。 - 首次运行的野指针问题:首次运行时直接将
root赋值给prev,后续cJSON_Delete(root)会释放该内存,导致prev变成悬空指针,后续使用会引发未定义行为。
修复后的代码
cJSON * prev = NULL, *current = NULL; bool compare = false; bool compareJSON(cJSON *i,cJSON *j) { if (i->type != j->type) { return false; } if (i->type == cJSON_Number && (i->valueint != j->valueint)) { return false; } if (i->type == cJSON_String && strcmp(i->valuestring,j->valuestring)){ return false; } if (i->type==cJSON_Array) { cJSON *ic = i->child, *jc = j->child; while (ic && jc) { if (!compareJSON(ic, jc)) { return false; } ic = ic->next, jc = jc->next; } if (ic || jc) return false; } if (i->type == cJSON_Object) { cJSON *ic = i->child; while (ic) { cJSON *jc = cJSON_GetObjectItem(j,ic->string); if (!jc || !compareJSON(ic,jc)){ return false; } ic = ic->next; } cJSON *jc = j->child; while (jc) { cJSON *ic=cJSON_GetObjectItem(i,jc->string); if (!ic || !compareJSON(ic,jc)){ return false; } jc = j->next; } } return true; } bool compareContents(){ int fd = open("/tmp/abc.txt", O_RDONLY); char* data = (char *)malloc(st.st_size + 1); //st.st_size obtained from fstat int n = read(fd, data, st.st_size); data[n] = '\0'; cJSON* root = cJSON_Parse(data); if (!root) { // 处理JSON解析失败的异常情况 if (fd >= 0) close(fd); if (data) free(data); return false; } compare = false; if(prev == NULL){ // 首次运行 // 复制root对象给prev,避免root被释放后prev悬空 prev = cJSON_Duplicate(root, 1); } else { // 释放旧的prev对象,避免内存泄漏 cJSON_Delete(prev); prev = current; } // 释放旧的current对象,再赋值新的复制结果 if (current) { cJSON_Delete(current); } current = cJSON_Duplicate(root, 1); if (prev && current) { compare = compareJSON(prev, current); } // 清理资源 if (fd >= 0) close(fd); if (access("/tmp/abc.txt", F_OK) == 0 && remove("/tmp/abc.txt") != 0){ printf("Error deleting the file\n"); } if (data) free(data); if (root) cJSON_Delete(root); return compare; }
关键修复点
- 首次运行逻辑修正:不再直接绑定
root到prev,而是通过cJSON_Duplicate复制独立对象,避免root被释放后prev成为野指针。 - 旧对象释放逻辑:每次更新
prev和current前,先调用cJSON_Delete释放旧对象,彻底避免内存泄漏。 - 增加异常处理:新增JSON解析失败的分支,提前清理资源,防止空指针引发的崩溃。
内容的提问来源于stack exchange,提问作者bvj0412
相关产品推荐
相关产品推荐

