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

C语言String Array函数返回空值,内部可打印外部无输出求助

问题分析与修复:枚举目录文件的指针错误

核心错误点

  • 悬空指针导致未定义行为
    getFiles里的buffer是栈上的局部变量,函数执行完毕后栈内存会被系统回收。你在循环中执行dirs[x] = buffer;,让所有数组元素都指向这块即将失效的栈内存。函数内部打印时栈内存还没被覆盖,所以能偶然看到一个结果,但回到main后这块内存已经无效,访问它就会出现无输出甚至程序崩溃的情况。

  • 字符串内存分配遗漏终止符空间
    strlen(de->d_name)只返回字符串的有效字符长度,不包含末尾的\0。你分配内存时用length*sizeof(char),会导致strcpy写入时越界,破坏内存。正确做法是分配(length + 1) * sizeof(char)。

  • 逻辑错误导致内存泄漏
    你先给dirs[x]分配了内存并完成strcpy(dirs[x], buffer);,紧接着又把dirs[x]指向buffer,等于之前的内存分配完全没用,还造成了内存泄漏。

  • 无效的内存释放代码
    return dirs;之后的free代码永远不会执行,返回的数组内存无法被正确释放,需要把释放逻辑移到调用方(main函数)。

  • 未处理数组越界风险
    你预设total=10,如果目录中文件数量超过10个,会导致dirs数组越界写入,破坏内存。


修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

#define BUFFER_SIZE 4096

// 提前声明函数,放在main前更规范
char **getFiles(int *file_count);

int main(){
    int file_count = 0;
    char **files = getFiles(&file_count);
    
    if (files == NULL) {
        printf("获取文件列表失败\n");
        return 1;
    }

    printf("\nFUNCTION RETURN:\n");
    for (int i = 0; i < file_count; i++) {
        printf("%s\n", files[i]);
        // 先释放每个字符串的内存
        free(files[i]);
    }
    // 再释放数组本身的内存
    free(files);
    
    return 0;
}

char **getFiles(int *file_count){
    // 动态扩容的初始大小
    int total = 10;
    char **dirs = malloc(total * sizeof(char *));
    if (dirs == NULL) {
        printf("内存分配失败\n");
        return NULL;
    }

    struct dirent *de;  
    DIR *dr = opendir("."); 

    if (dr == NULL) { 
        printf("打开目录失败\n");
        free(dirs);
        return NULL; 
    } 

    int x = 0;
    while ((de = readdir(dr)) != NULL){ 
        // 跳过.和..目录(可选,看需求)
        if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
            continue;
        }

        // 检查是否需要扩容数组
        if (x >= total) {
            total *= 2;
            char **temp = realloc(dirs, total * sizeof(char *));
            if (temp == NULL) {
                printf("数组扩容失败\n");
                // 释放已分配的字符串内存
                for (int i = 0; i < x; i++) {
                    free(dirs[i]);
                }
                free(dirs);
                closedir(dr);
                return NULL;
            }
            dirs = temp;
        }

        int length = strlen(de->d_name);
        // 为字符串分配内存,包含\0的位置
        dirs[x] = malloc((length + 1) * sizeof(char));
        if (dirs[x] == NULL) {
            printf("字符串内存分配失败\n");
            // 清理已分配的内存
            for (int i = 0; i < x; i++) {
                free(dirs[i]);
            }
            free(dirs);
            closedir(dr);
            return NULL;
        }
        // 直接复制文件名到分配的内存
        strcpy(dirs[x], de->d_name);
        x++;
    }

    closedir(dr);     
    // 把实际文件数量返回给调用方
    *file_count = x;
    return dirs;
}

关键修改说明

  1. 增加file_count参数,让调用方知道返回的数组里有多少个文件。
  2. 去掉了栈上的buffer,直接把文件名复制到堆内存分配的空间里,避免悬空指针。
  3. 修复了字符串内存分配的长度问题,加上了\0的位置。
  4. 增加了数组动态扩容逻辑,避免文件数量超过预设值导致越界。
  5. 完善了错误处理,在内存分配失败或目录打开失败时,清理已分配的内存再返回。
  6. 把内存释放的逻辑移到main函数里,确保所有堆内存都能被正确释放。

内容的提问来源于stack exchange,提问作者Jacob Thevenot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:38:09