这是在 c 中释放内存的可接受方法吗?

Is this an acceptable way to deallocate memory in c?

提问人:gotter 提问时间:2/27/2023 最后编辑:gotter 更新时间:2/27/2023 访问量:108

问:

我有一个函数,它读取文件并为文件内容分配内存,并将文件内容分配给指针,然后返回指针。然后,我使用循环遍历字符串并使用指针算术打印每个字符。

我很确定我可以/应该使用 realloc 在每次迭代中重新分配更少的内存,而不是使用计数器跟踪迭代,但我不确定如何实现它。

因此,在代码末尾,当我调用时,我从指针变量中减去计数器,以解除分配指针最初指向的地址。free()contents

以下是我用来读取文件的代码以及我的循环所在的主函数:

char *read_file(const char *filename) {
    FILE *fp = fopen(filename, "r");
    if (fp == NULL) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    // Obtain information about the file
    struct stat st;
    if (fstat(fileno(fp), &st) != 0) {
        perror("Failed to get file information");
        exit(EXIT_FAILURE);
    }
    size_t file_size = st.st_size;

    // Allocate a buffer to hold the contents of the file
    char *buffer = (char *) malloc(file_size + 1);
    if (buffer == NULL) {
        perror("Failed to allocate memory");
        exit(EXIT_FAILURE);
    }

    // Read the contents of the file into the buffer
    size_t bytes_read = fread(buffer, 1, file_size, fp);
    buffer[bytes_read] = '\0';

    // Close the file and return the buffer
    fclose(fp);
    return buffer;
}




int main() {
    char *contents = read_file("testNote.txt");
    int counter = 0;

    while (*contents != '\0') {

        printf("%c", *contents);

        ++counter;
        ++contents;
    }

    free(contents - counter);

    return 0;
}

据我在实验后所知,这是按照我所认为的方式工作的,但我只是想确保我在这里没有做任何有害的事情

c 内存 malloc 分配 realloc

评论

0赞 Fe2O3 2/27/2023
要注册字节数,请在函数中使用,然后在 .两者都应该是前者......而且,无需从 转换返回值。(除非有迫切的原因,否则重新分配缓冲区以缩小缓冲区可能会产生过多的开销。size_tintmain()malloc()
0赞 Irelia 2/27/2023
理想情况下,不应递增或递减分配的指针。创建一个临时指针并改为递增该指针。
0赞 tstanisl 2/27/2023
int对于大文件,可能会溢出。

答:

6赞 dbush 2/27/2023 #1

你正在做的事情会奏效。每次递增时,也会递增,因此为您提供可以释放的原始指针。contentscountercontents - counter

当然,更好的方法是使用临时指针在分配的内存中递增,以便您可以使用原始 to .free

int main() {
    char *contents = read_file("testNote.txt");
    char *tmp = contents;

    while (*tmp != '\0') {

        printf("%c", *tmp);

        ++tmp;
    }

    free(contents);

    return 0;
}

评论

0赞 tstanisl 2/27/2023
最好使用 loop:forfor (char *tmp = contents; *tmp != '\0'; ++tmp) { ... }
1赞 Nick ODell 2/27/2023 #2

不,这不安全。

假设您读取的文件大于 2147483647 字节或大约 2 GB。然后,当您到达文件末尾时,overflow 的值为负数。当你减去 时,你得到的地址与你得到的地址不同。最好的情况是它崩溃。最坏的情况是它会损坏堆并继续运行。countercontents - countermalloc()

我建议使用@dbush的建议。即使您可以保证不会获得 2GB 的文件,它们的代码仍然更容易推理。