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

C语言无限循环内覆盖全局char数组与char指针的选型问题

无限循环场景下char数组和char指针的选择方案

首先明确:你给出的两个初始实现都存在严重问题,需要先修正错误再谈方案选择。

初始实现的问题分析

指针版本问题

cJSON_PrintUnformatted返回的是堆上动态分配的字符串内存,需要调用者主动调用free释放。你当前的实现每次循环直接覆盖recv_data指针,会丢失上一次分配的内存地址,完全无法释放,无限循环下会持续消耗内存直到程序崩溃,属于必现的内存泄漏问题。

数组版本问题

这个版本的问题比指针版本更严重:

  1. 依然存在内存泄漏:cJSON_PrintUnformatted返回的堆内存没有被释放,拷贝完内容就直接丢了指针
  2. 存在栈溢出风险:如果输出的JSON字符串长度超过255,strcpy会直接越界写栈内存,轻则程序崩溃,重则被注入执行恶意代码
  3. 未做边界检查,超长内容会被截断但不会自动补字符串终止符,后续使用可能出现乱码

两种方案的正确实现和适用场景

不存在绝对的孰优孰劣,两种方案都可以使用,只要做好对应的内存处理:

方案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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 21:39:02