A good working example how subtle bugs can crash you program.
The BUG
fclose(file);
Above statement will always close a valid file handle which was returned after a fopen() call was made.By chance the fopen() failed , we shouldnt be attempting to close the file handle.Attempting to do so will crash the program.
The Solution, before closing a file check its validity:
if (file) {
fclose(file);
}
If the aboce program was implemented mainly in C++, a smart resource handler could be used , which is based on the RAII concept[Resource Acquisation/allocation Is Initialisation]
The file (resource) could be wrapped in a object ( when object goes out of scope, it calls its destructor ) and the clean up of object can be automated.
Below is an example
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#define CHATTY 1 //CHATTY 0 //to Disable chatty message when functions called
using namespace std;
class myFileobject
{
private:FILE * __file = nullptr;
public:
myFileobject (const char *fileName)
{
__file = fopen (fileName, "r");
#if CHATTY
cout << "myFileobject(const char* fileName) " << fileName << "\n";
#endif
}
myFileobject (FILE * fp = nullptr):__file (fp)
{
#if CHATTY
cout << "myFileobject(FILE* fp=nullptr) \n";
#endif
};
~myFileobject ()
{
#if CHATTY
cout << "~myFileobject() __file \n";
#endif
if (__file)
fclose (__file);
}
operator bool ()
{
#if CHATTY
cout << "operator bool\n";
#endif
return (bool) __file;
}
operator FILE *()
{
#if CHATTY
cout << "operator FILE*\n";
#endif
return __file;
}
};
#ifdef __cplusplus
#define filename "main.1cpp"
#else
#define filename "main.c"
#endif
// Summary: Opens fileName and reads maximum maxByteCount number of bytes from the first line of it and prints it on stdout.
// fileName: the path to the file to open
// maxByteCount: the maximum number of bytes to read
void
PrintFirstLine (const char *fileName, int maxByteCount)
{
//FILE * file = fopen(fileName, "r");
myFileobject file (fileName);
char buffer[maxByteCount + 1]; // +1 for reserving space for the terminating zero
if (file)
{
fgets (buffer, sizeof (buffer), file);
printf ("First line read: %s\n", buffer);
}
else
{
printf ("Nothing read.\n");
}
//fclose(file);
}
int
main ()
{
PrintFirstLine (filename, 100);
return 0;
}