微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

分配和释放动态内存

如何解决分配和释放动态内存

我编写了一个短程序,它从存储卡中读取 JPEG 并将 JPEG 作为单独的文件作为输出写入。该程序按我的预期工作,但我知道我的代码编写得很差,因为没有从堆中释放动态内存。

我曾尝试在我的代码中使用 fclose()free(),但在我这样做时出现以下错误

free(): double free detected in tcache 2
Aborted

我已经注释掉了这些函数,并且我的代码按预期工作。 我想知道为什么当我尝试使用这两个函数时它不起作用。我做错了什么?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// define/declare variables
typedef uint8_t BYTE;
FILE *outptr; 

int main(int argc,char *argv[])
{
// declare variables
int counter = 0;

// ensure correct command-line useage
if (argc != 2)
{
    printf("Useage: ./recover memorycard\n");
    return 1;
}

// open memory card to read
FILE *inptr = fopen(argv[1],"r");
if (inptr == NULL)                    // ensure enough memory
{
    fprintf(stderr,"Could not open file");
    return 2;
}

// read into infile,512 bytes at a time until end of file
BYTE buffer[512];
while (fread(buffer,sizeof(BYTE),512,inptr) == 512)
{
    // if JPEG headerfile is found
    if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
    {
        if (counter > 0)             // if not first JPEG
        {
            // close prevIoUs file
     //     fclose(outptr);                            // here is the issue
     //     free(outptr);                              // and here
        }

        // allocate memory for new file
        char *outfile = malloc(sizeof(BYTE) * 512);
        if (outfile == NULL)
        {
            printf("Not enough memory for output file\n");
            fclose(inptr);
            return 3;
        }

        // write new file name
        sprintf(outfile,"%03i.jpg",counter);

        // open new file
        outptr = fopen(outfile,"w");
        if (outptr == NULL)
        {
            fprintf(stderr,"Could not open file.\n");
            fclose(inptr);
            return 4;
        }

        // write 512 bytes from infile into new file
        fwrite (buffer,outptr);

        counter++;

    }

    // if not start of new JPEG
    else if (buffer[0] != 0xff || buffer[1] != 0xd8 || buffer[2] != 0xff || (buffer[3] & 0xf0) != 0xe0)
    {
        // if already found JPEG
        if (counter > 0)
        {
            // keep writing into JPEG
            fwrite (buffer,outptr);
        }

        continue;
    }

}
// Close remaining files once gone through memory card
//    fclose(inptr);                        // here
//    free(inptr);                          // and here
}

解决方法

在循环的第一次迭代中,outptr 变量未初始化,因此对其执行的任何操作都会带来未定义的行为。
具体来说,您没有为它分配任何从 fopen() 获得的值,因此您不应该 fclose() 它。
此外,您还没有为它分配从 malloc()calloc() 获得的任何值,因此您不应free() 它。

当您需要写入文件时,您需要 fopen() 一个文件,只要需要(您写入它)就保留一个指向它的指针,并在完成后 fclose()。文件处理不需要 malloc()free()

以下是稍微简化的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// define/declare variables
typedef uint8_t BYTE;
FILE *outptr = NULL; 

int main(int argc,char *argv[])
{
    // declare variables
    int counter = 0;

    // ensure correct command-line useage
    if (argc != 2)
    {
        printf("Useage: ./recover memorycard\n");
        return 1;
    }

    // open memory card to read
    FILE *inptr = fopen(argv[1],"r");
    if (inptr == NULL)                    // ensure enough memory
    {
        fprintf(stderr,"Could not open file");
        return 2;
    }

    // read into infile,512 bytes at a time until end of file
    BYTE buffer[512];
    while (fread(buffer,sizeof(BYTE),512,inptr) == 512)
    {
        // if JPEG headerfile is found
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            if (outptr != NULL)             // previous file is opened
            {
                fclose(outptr);             // close it
            }

            char outfilename[ 512];         // output file name

            sprintf(outfilename,"%03i.jpg",counter ++);

            // open new file
            outptr = fopen(outfilename,"w");
            if (outptr == NULL)
            {
                fprintf(stderr,"Could not open file.\n");
                fclose(inptr);
                return 4;
            }
        }

        // whether it's a new or still the same file...
        if(outptr != NULL)
        {
            // keep writing into JPEG
            fwrite (buffer,outptr);
        }
    }

    fclose(outptr);         // close the last file created
    fclose(inptr);          // as well as the input
}

我删除了对文件名的 malloc 调用 - 它足够短,可以在堆栈上自动分配,并且您不需要在使用后free(您忘记这样做了),顺便说一句,因此造成内存泄漏...)

我注意到您在 writeif 分支中执行完全相同的 else,因此我将其移到了条件之外。

我还删除了 continue; 指令,因为一旦控制到达右大括号,循环就会继续。

最重要的是:我添加了初始化 FILE* outptr = NULL; 以便它可以检查文件指针变量是否已成功打开文件,而不是检查明显未连接的 {{1} } 变量。

,
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// define byte
typedef uint8_t BYTE;


int main(int argc,char *argv[])
{
    // ensure correct command-line useage
    if (argc != 2)
    {
        printf("Useage: ./recover memorycard\n");
        return 1;
    }

    // open memory card 
    FILE *inptr = fopen(argv[1],"r");
    if (inptr == NULL)                    
    {
        fprintf(stderr,"Could not open file");
        return 2;
    }

    // buffer for file names
    char output[8];
    
    // keep track of file number for file names
    int counter = 0; 
    
    // pointer to write JPEGs to
    FILE *outptr = NULL;
    
    // read into infile,inptr) == 512)
    {
        // New JPEG signatiture found
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            // if not first JPEG,close previous output file
            if (outptr != NULL)
                fclose(outptr);
            
            // write new file name
            sprintf(output,counter);
            
            // open new file
            outptr = fopen(output,"Could not open file.\n");
                fclose(inptr);
                return 4;
            }
            
            // increment file counter
            counter++;
        }

        // if output file is already open
        if (outptr != NULL)
        {
            // keep writing into JPEG
            fwrite (buffer,outptr);
        }
    }
    
    // close final file if still open
    if (outptr != NULL)
        fclose(inptr);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。