在C语言中如何释放字符指针

7

我正在尝试使用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[]这样声明的变量吗?如果是,如何释放?

3个回答

15

当你声明一个数组时:

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;

你只创建了一个指向 char 的变量,但它还没有指向任何内容。在初始化之前尝试使用它是错误的:

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是系统调用(或者说是对它们的包装),而堆栈数组则不是。 - KAction
@KAction 'malloc' 在堆上分配内存! - at_Root

6
你可以使用char *command;,但是你必须为command分配一些内存,以便通过调用malloc()来引用它,并且当你完成对该内存的使用时,必须再次通过调用free()来释放它。
如你所见,这比使用固定大小的数组(就像你现在做的那样)要麻烦得多,但也可以使其更加安全,因为你可以创建一个完全正确大小的缓冲区,而不是希望命令的总长度不会超过100个字符。
除此之外,你的代码还有一个问题:函数返回的filetype指针指向了file_details数组中的某个位置,但是当执行return语句时,编译器将清除该数组,因此函数返回的指针引用了一些被标记为“可以用于其他目的”的内存。
如果get_file_type的结果每次只需要针对一个文件有效,则可以将file_details数组声明为static,这样它将跨函数调用保留下来。

你可以这样做,但是你必须记得在调用函数中调用 free 以避免内存泄漏。 - Bart van Ingen Schenau

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

但是你能向我解释一下如何做吗? - Sandeep Manne
一方面,根据“path”和“filename”的长度动态分配缓冲区可能是有意义的,而不是默默地允许缓冲区溢出。(C99可变长度数组可以解决此问题,但建议使用“snprintf”而不是“sprintf”)。 - jamesdlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接