C语言无限循环内覆盖全局char数组与char指针的选型问题
无限循环场景下char数组和char指针的选择方案
首先明确:你给出的两个初始实现都存在严重问题,需要先修正错误再谈方案选择。
初始实现的问题分析
指针版本问题
cJSON_PrintUnformatted返回的是堆上动态分配的字符串内存,需要调用者主动调用free释放。你当前的实现每次循环直接覆盖recv_data指针,会丢失上一次分配的内存地址,完全无法释放,无限循环下会持续消耗内存直到程序崩溃,属于必现的内存泄漏问题。
数组版本问题
这个版本的问题比指针版本更严重:
- 依然存在内存泄漏:
cJSON_PrintUnformatted返回的堆内存没有被释放,拷贝完内容就直接丢了指针 - 存在栈溢出风险:如果输出的JSON字符串长度超过255,
strcpy会直接越界写栈内存,轻则程序崩溃,重则被注入执行恶意代码 - 未做边界检查,超长内容会被截断但不会自动补字符串终止符,后续使用可能出现乱码
两种方案的正确实现和适用场景
不存在绝对的孰优孰劣,两种方案都可以使用,只要做好对应的内存处理:
方案1:char数组方案(适用于JSON长度可预判的场景)
如果你可以100%确定输出的JSON最大长度不会超过设定的数组大小,或者业务可以接受超长内容截断,选数组方案更省心,不需要担心内存释放遗漏的问题:
// 长度可以根据实际业务场景调整到足够大的冗余值 #define RECV_BUF_SIZE 1024 char recv[RECV_BUF_SIZE] = {0}; int main(){ // 省略其他逻辑 while(1){ // 省略其他逻辑 char *tmp_json = cJSON_PrintUnformatted(root); if (tmp_json != NULL) { // 用strncpy做边界限制 strncpy(recv, tmp_json, RECV_BUF_SIZE - 1); // 手动补终止符,避免截断后无结束标识 recv[RECV_BUF_SIZE - 1] = '\0'; // 释放cJSON分配的堆内存 free(tmp_json); tmp_json = NULL; } // 后续正常使用recv即可,传入其他函数也无问题 // 省略其他逻辑 } }
方案2:char指针方案(适用于JSON长度不确定的场景)
如果无法预判JSON长度,不能接受内容截断,选指针方案更灵活,只要严格遵循「分配-使用-释放」的逻辑就不会出现内存泄漏:
int main(){ char *recv_data = NULL; // 省略其他逻辑 while(1){ // 省略其他逻辑 recv_data = cJSON_PrintUnformatted(root); if (recv_data == NULL) { // 自行添加错误处理逻辑 continue; } // 正常使用recv_data,传入其他函数都无问题 // 省略使用逻辑 // 用完必须释放内存 free(recv_data); recv_data = NULL; // 置空避免野指针 } }
注意:不需要把
recv_data定义为全局变量,放在main函数局部作用域即可,减少全局变量污染。
总结
如果你的业务场景下JSON最大长度可控,优先选数组方案更省心;如果JSON长度波动大无法预判,选指针方案即可,只要每次用完记得释放就不会有内存泄漏风险。
内容的提问来源于stack exchange,提问作者bvj0412
相关产品推荐
相关产品推荐

