【问题标题】:Free char pointer in cc中的免费char指针
【发布时间】:2011-04-09 02:09:25
【问题描述】:

我正在尝试使用 c 代码找出文件类型,这是代码

char *get_file_type(char *path, char *filename)
{
    FILE *fp;
    char command[100];
    char file_details[100];
    char *filetype;

    sprintf(command, "file -i %s%s", path, filename);
    fp = popen(command, "r");
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit(1);
    }
    while (fgets(file_details,  sizeof(file_details)-1, fp) != NULL) {
         filetype = (strtok(strstr(file_details, " "), ";"));
    }

    pclose(fp);
    return filetype;
}

这里不用声明command[],我可以使用*command 吗?我尝试使用它,但它引发了异常。我们不需要释放声明为 command[] 的变量吗?如果是怎么办?

【问题讨论】:

    标签: c string pointers char


    【解决方案1】:

    当你声明一个数组时:

    char command[100];
    

    编译器为其分配内存(在本例中为 100 个字符),command 指向该内存的开头。您可以访问已分配的内存:

    command[0]  = 'a';  // OK
    command[99] = 'A';  // OK
    command[100] = 'Z'; // Error: out of bounds
    

    但是你不能改变command的值:

    command = NULL;     // Compile-time error
    

    command 超出范围时,内存将被自动释放。


    当你声明一个指针时:

    char *commandptr;
    

    您只创建了一个指向chars 的变量,但它还没有指向任何东西。尝试在不初始化的情况下使用它是错误的:

    commandptr[0] = 'A';   // Undefined behaviour; probably a segfault
    

    你需要自己使用malloc分配内存:

    commandptr = malloc(100);
    if (commandptr) {
        // Always check that the return value of malloc() is not NULL
        commandptr[0] = 'A';  // Now you can use the allocated memory
    }
    

    完成后释放它:

    free(commandptr);
    

    【讨论】:

    • 实际上,栈数组并没有被释放,因为它不需要。老实说,malloc 和 free 是系统调用(嗯,它们的包装器),而堆栈数组不是。
    【解决方案2】:

    您可以使用char *command;,但是,您必须为command分配一些内存,以便通过调用malloc()来引用,当您完成该内存时,必须通过调用再次释放它到free()

    正如您所看到的,这比使用固定大小的数组(就像您现在所做的那样)要多得多,但它也可以变得更安全,因为您可以创建一个大小正好合适的缓冲区,而不是希望命令的总长度不会超过 100 个字符。

    除此之外,您的代码还有一个问题:函数返回的filetype 指针指向数组file_details 中的一个位置,但是编译器在执行return 语句时会清理该数组,所以函数返回的指针指向一些标记为“可用于其他目的”的内存。

    如果get_file_type的结果一次只对一个文件有效不是问题,你可以将file_details数组声明为static,这样在调用函数时它会被保留.

    【讨论】:

    • 你可以,但是你必须记住在调用函数中调用free以避免内存泄漏。
    【解决方案3】:

    你为什么要改变它?对于临时缓冲区,人们通常用 [] 声明数组,因此他们不必担心垃圾处理。

    【讨论】:

    • 但是你能解释一下怎么做吗?
    • 一方面,根据pathfilename 的长度动态分配缓冲区可能比静默允许缓冲区溢出更有意义。 (不过,C99 可变长度数组可以解决这个问题。建议使用 snprintf 而不是 sprintf。)
    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 2021-11-26
    • 2020-03-16
    • 2021-01-26
    • 2012-03-19
    • 2021-08-11
    • 1970-01-01
    • 2011-04-10
    相关资源
    最近更新 更多