Error handling when opening multiple files in C language

Asked 2 years ago, Updated 2 years ago, 37 views

If you want to open multiple files in C language and write
How should I write down the error handling?

I thought about the following, but in the second file open
The processing of an error is disgusting.

 int func1 (char*fname1, char*fname2)
{
    FILE*fp1;
    FILE*fp2;

    if(((fp1=fopen(fname1,"w"))==NULL)
    {
        fprintf(stderr, "fname1 open error.\n");
        return-1;
    }
    if((fp2=fopen(fname2, "w"))==NULL)
    {
        fprintf(stderr, "fname2 open error.\n");
        fclose(fp1);// This is disgusting
        return-1;
    }
    intret;
    ret = func2(fp1,fp2); // The action of writing to a file
    fclose(fp1);
    fclose(fp2);
    if(ret!=0)
    {
        fprintf(stderr, "error occurred in func2.\n";
        return-1;
    }
    return 0;
}

c

2022-09-30 20:33

4 Answers

In this case, goto can be used to write beautifully, so if there is no problem using it, how about writing as follows?

 int func1 (char*fname1, char*fname2)
{
    intr = 0; // Used for return value
    FILE*fp1 = NULL;
    FILE*fp2 = NULL;

    if(((fp1=fopen(fname1,"w"))==NULL)
    {
        fprintf(stderr, "fname1 open error.\n");
        r = -1;
        goto cleanup;
    }
    if((fp2=fopen(fname2, "w"))==NULL)
    {
        fprintf(stderr, "fname2 open error.\n");
        r = -1;
        goto cleanup;
    }
    intret;
    ret = func2(fp1,fp2); // The action of writing to a file
    if(ret!=0)
    {
        fprintf(stderr, "error occurred in func2.\n";
        r = -1;
        goto cleanup;
    }

US>cleanup
    if(fp1!=NULL){
        fclose(fp1);
    }
    if(fp2!=NULL){
        fclose(fp2);
    }
    return;
}


2022-09-30 20:33

I also use goto, but it's a shame that you can't use goto in any pattern.

FILE*fp1=fopen(fname1,"w");
FILE* fp2 = fopen(fname2, "w");

if(fp1==NULL||fp2==NULL)
{
    (fp1 == NULL)?fprintf(stderr, "fname1 open error.\n")—fclose(fp1);
    (fp2==NULL)?fprintf(stderr, "fname2 open error.\n")—fclose(fp2);
    return-1;
}

// file processing
・・・

fclose(fp1);
fclose(fp2);


2022-09-30 20:33

It's almost the same as Kyosuke Kameda's answer, but there's also a way to not make NULL decisions during cleanup.

 int func1 (char*fname1, char*fname2)
{
    intr = 0;
    FILE*fp1;
    FILE*fp2;

    if(((fp1=fopen(fname1,"w"))==NULL)
    {
        fprintf(stderr, "fname1 open error.\n");
        r = -1;
        goto err_open1;
    }
    if((fp2=fopen(fname2, "w"))==NULL)
    {
        fprintf(stderr, "fname2 open error.\n");
        r = -1;
        goto err_open2;
    }
    intret = func2(fp1,fp2); // The action of writing to a file
    if(ret!=0)
    {
        fprintf(stderr, "error occurred in func2.\n";
        r = -1;
        gotoerr_func2;
    }

// cleanup
err_func2:
    fclose(fp2);
err_open2:
    fclose(fp1);
err_open1:
    return;
}

Each action that requires error determination

hoge cleanup action;
err_hoge:

It's a group of things like that
In this way, the order in which fp1 and fp2 are closed is reversed from the original
It is necessary to, but from experience, it is often better to release files and memory in reverse order of opening and securing them.
If you have to close it in order of the original, this method may be a drawback.


2022-09-30 20:33

The direct attack method can also be implemented using the cleanup attribute in the GCC proprietary extension.Please be careful when using it as it is not available with other compilers.

Quoted from Wikipedia article "Resource Acquisition Is Initialization"

static inline void fclose(FILE**fp) { if(*fp)fclose(*fp);}
#define_cleanup_fclose___attribute_((cleanup(fclose)))))

void example_usage(){
  _cleanup_fclose_FILE* logfile=fopen("logfile.txt", "w+");
  fputs("hello logfile!", logfile);
}


2022-09-30 20:33

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.