【问题标题】:Overwriting global char array vs global char pointer in a loop in C在C中的循环中覆盖全局char数组与全局char指针
【发布时间】:2021-12-05 20:48:52
【问题描述】:

我有一个无限的 while 循环,我不确定我应该使用 char 数组还是 char 指针。该值不断被覆盖并用于其他功能。使用 char 指针,我知道可能存在内存泄漏,所以最好使用数组吗?

char *recv_data = NULL;

int main(){
.....
  while(1){
   .....
   recv_data = cJSON_PrintUnformatted(root);

  .....
  
  }
} 

char recv[256] = {0};

int main(){
.....
  while(1){
   .....
   strcpy(recv, cJSON_PrintUnformatted(root));

  .....
  
  }
} 

【问题讨论】:

  • 第二个版本有内存泄漏,因为你永远无法释放函数返回的数组。
  • 你是实现cJSON_PrintUnformatted()功能的人吗?或者它是给定的,你必须使用它?
  • @einpoklum cJSON_PrintUnformatted() 是一个标准的 JSON/cJSON 函数,用于打印 cJSON 对象/项目,它返回一个指向 char 的指针
  • C 没有“标准”JSON 库...你确定你使用的是好的吗?我不是他们的专家,但你考虑过替代品吗? This one 很受欢迎。

标签: arrays c pointers char


【解决方案1】:

应该首选第一个版本。

  1. 它对返回字符串的大小没有限制。
  2. 您可以使用free(recv_data) 修复内存泄漏。

第二个版本有这些错误:

  1. 无法释放从函数返回的内存,因为您从未将它分配给可以传递给 free() 的变量。
  2. 效率稍低,因为它执行了不必要的复制。

【讨论】:

  • 感谢您的回答。但是如果我在recv_data = cJSON_PrintUnformatted(root); 之后立即使用free(),在尝试再次设置'recv_data' 时,while 循环的下一次迭代中不会出现seg_fault 吗?
  • 否,因为下一次迭代再次调用该函数,它分配了另一个数组。
  • 我不确定我是否理解您所说的分配另一个数组是什么意思,您能否进一步澄清一下?是因为它是一个全局指针吗?我还必须在另一个函数中访问recv_data。这 while(1) 在一个线程中运行,我有另一个线程,我在其中读取 recv_data 并打印它的值。那么释放它并将其设置为 NULL 不会有问题吗?
  • 我假设cJSON_PrintUnformatted(root); 在内部调用malloc() 来创建它返回指针的数据。所以每次你调用它时,它都会为那个 JSON 对象分配新的内存。
  • 这就是为什么如果你不释放它就会出现内存泄漏。
【解决方案2】:

根据您的使用方式,cJSON_PrintUnformatted 返回一个指向 char 数组的指针。由于没有输入参数,它可能会在函数内部动态分配内存。您可能必须 free 那个内存。所以你需要返回的指针才能自己释放内存。

第二个选项丢弃返回的指针,因此您失去了释放分配的内存的唯一方法。因此它将保持分配状态 -> 内存泄漏。

当然,这一切都取决于功能是如何实现的。也许它只是操作一个全局数组并返回一个指向它的指针,所以不需要释放它。

【讨论】:

    【解决方案3】:

    确实,正如@Barmar 指出的那样,第二个版本存在内存泄漏。

    然而,即使你要修复内存泄漏,你仍然不能真正使用你的代码的第一个版本:对于第一个版本,你必须在编译时决定返回的字符串的最大长度通过cJSON_PrintUnformatted()。现在,

    • 如果您选择的值太strcpy() 函数将超出数组边界并损坏您的堆栈。
    • 如果您选择一个高到安全的值 - 您可能不得不超过程序堆栈的可用空间量,从而导致Stack Overflow(是的,就像这个站点的名称一样)。您可以使用strncpy() 解决这个问题,给出最大大小 - 然后您将拥有一个截断的字符串。

    因此,除了使用cJSON_PrintUnformatted() 的返回值所指向的任何内存(它可能是堆分配的内存)之外,您真的别无选择。另外 - 当它已经在那里供您使用时,为什么要复制它?偷懒:-)

    PS - 真正应该发生的是cJSON_PrintUnformatted() 将缓冲区和缓冲区大小作为参数,使其调用者能够更好地控制内存分配和资源限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多