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

动态char指针数组内存分配异常问题及调试工具咨询

问题原因分析

核心内存错误点

在increaseArraySize函数中存在致命内存操作错误:

  • 用memcpy将旧数组的指针复制到新数组后,代码循环释放了旧数组中每个元素指向的字符串内存:
    for (int i = 0; i < *currentMaxElementsPtr; ++i) {
      free((void *)arrayPtr[i]);
    }
    
    新数组的指针与旧数组指针指向同一块字符串内存,释放旧数组元素后,新数组的指针直接变成悬空指针。后续访问这些指针时,内存内容已失效或被覆盖,必然出现元素损坏、顺序错乱的现象。
  • 正确逻辑:旧数组的元素指针已转移到新数组,此处只需释放旧数组本身的指针数组内存(free(arrayPtr)),字符串内存的释放应在main函数中统一处理。

额外潜在问题

路径拼接存在类型错误:

  • concat(dirPath, (const char *)&root)中,&root取的是字符串常量的指针地址而非内容,正确写法应为concat(dirPath, root),否则会拼接出错误路径甚至触发内存越界。
  • 同理,concat(pathToDir, (const char *)&entity->d_name)需改为concat(pathToDir, entity->d_name)。
修复方案
  1. 修改increaseArraySize函数,移除错误的元素释放代码:
    const char **increaseArraySize(const char **arrayPtr,
                                   int *currentMaxElementsPtr, int newMaxElements) {
      int totalNewMaxElements = *currentMaxElementsPtr + newMaxElements;
      const char **newSizeArray = malloc(totalNewMaxElements * sizeof(char *));
      if (newSizeArray == NULL) {
        fprintf(stderr, "Fatal: failed to allocate new array space");
        exit(0);
      }
      memcpy(newSizeArray, arrayPtr, *currentMaxElementsPtr * sizeof(char *));
    
      // 移除以下错误的循环释放代码
      // for (int i = 0; i < *currentMaxElementsPtr; ++i) {
      //   free((void *)arrayPtr[i]);
      // }
    
      free((void *)arrayPtr); // 仅释放旧数组的指针数组内存
      *currentMaxElementsPtr = totalNewMaxElements;
      return newSizeArray;
    }
    
  2. 修复所有路径拼接的类型错误:
    • 将const char *pathToDir = concat(dirPath, (const char *)&root);改为const char *pathToDir = concat(dirPath, root);
    • 将const char *filePath = concat(pathToDir, (const char *)&entity->d_name);改为const char *filePath = concat(pathToDir, entity->d_name);
    • 将const char *newDir = concat(pathToDir, (const char *)&entity->d_name);改为const char *newDir = concat(pathToDir, entity->d_name);
内存分配调试工具推荐
  • Valgrind:老牌内存调试工具,可精准检测悬空指针、内存越界、内存泄漏等问题。运行命令:valgrind --leak-check=full ./your_program,会输出详细的错误位置与原因。
  • AddressSanitizer(ASAN):GCC/Clang内置内存检测工具,编译时添加-fsanitize=address参数(如gcc -fsanitize=address your_code.c -o scan_dir),运行程序时直接触发错误并定位到代码行,效率高于Valgrind。
  • GDB:结合断点调试,在数组扩容后、使用元素前设置断点,打印数组内容跟踪内存变化。比如在increaseArraySize返回前设断点,查看新数组元素是否已损坏。

内容的提问来源于stack exchange,提问作者Elia Riva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:35:09