The problem I have and can't understand is that I receive a segfault when trying to close the second file (fclose(ofp)).

Input file is a xml file that will generate food for output file.

At present time, input file is being read for parsing but no output for outfile is generated.

The error I get is:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7aae9c2 in _int_free () from /lib64/libc.so.6
gcc 4.5.2

The relevant code is:

FILE * openFile (char * filen_in, char * mode, unsigned short int err) {
    /* Open SAFT file.          */
FILE * fp;
    if ((fp = fopen (filen_in, mode)) == NULL) {
    error_handler(err);
}
return fp;
}

void closeFile (FILE * fp, unsigned short int err) {
    /* Close output file.       */
    if (fclose(fp) != 0) {
        error_handler(err);
    }
}

int main() {

    FILE *ifp;
    FILE *ofp;
    char * filen_in = "a.xml";
    char * filen_out = "out.txt";

    ifp = openFile(filen_in, "r", 1);
    ofp = openFile(filen_out, "a", 3);

    /* nr_chars = readSt(ifp); */

    closeFile(ifp, 2);
    closeFile(ofp, 4);

    return 0;
}

What is going here? How can I fix this?

My guess is that readST() is trashing memory, and when that happens it can affect anything or everything ion the program. There is nothing in the code you posted that should cause the problem because all it does is open and close the files.

Hi,

The entire code is below.
Besides trying to solve the segfault, if you have any comments that can help building better C please go ahead.

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

#define BUFSIZE 4


void error_handler(unsigned short int err) {
    char * error_desc;
    switch (err) {
        case 1: error_desc = "Input file could not be opened.\n";
            ;;
        case 2: error_desc = "Input file did not exist.\n";
            ;;
        case 3: error_desc = "Output file could not be opened\n";
            ;;
        case 4: error_desc = "Output file could not be closed.\n";
            ;;
        default: error_desc = "Unspecified error, aborting.\n";
            ;;
    }
    printf("Exiting with error %s\n", error_desc);
    exit(err);
}

FILE * openFile (char * filen_in, char * mode, unsigned short int err) {
    /* Open SAFT file.          */
    FILE * fp;
    if ((fp = fopen (filen_in, mode)) == NULL) {
        error_handler(err);
    }
    return fp;
}

void closeFile (FILE * fp, unsigned short int err) {
    /* Close output file.       */
    if (fclose(fp) != 0) {
        error_handler(err);
    }
}

char * parser(char ** p, unsigned int dif)
{
    /* Store first 2 chars of each string */
    /* printf("-------------- %d    %d  \n", p, *p);*/
    if (dif > 0) {
        ++*p;
    }
    return 0;
}

/* Reads SAFT-PT file and returns nr. of characters of xml file. */
unsigned long int readXml(FILE *f)
{
    register c;
    char ch;
    unsigned long int l = 0;                            /* Nr. of characters read.*/
    char * buffer = (char *) malloc(BUFSIZE * sizeof(char) + 1); /* +1 for \0 */
    char * initial = buffer;
    char * to_save = (char *) malloc(BUFSIZE * sizeof(char) + 1);

    printf("*****   readXml   *****\n");

        /*printf("%c", ch); */
    /* After buffer == EOF, parse the remaining text. */
    while ((c = getc(f)) != EOF) {
        ch = (char) c;
        ++l;

        if ( buffer - initial < BUFSIZE ) {
            *buffer = ch;
            ++buffer;               /* Points to next possible entry. At end.*/
        } else {
            ungetc(c, f);
            to_save = parser(& initial, buffer - initial);  
            buffer = initial;
        }
    }
    /* Parse the last characters. */
    to_save = parser(& initial, buffer - initial);  

    printf("\n");
    return l;
}

int main() {

    FILE *ifp;
    FILE *ofp;
    char * filen_in = "a.xml";
    char * filen_out = "out.txt";

    unsigned long int nr_chars;
    ifp = openFile(filen_in, "r", 1);
    ofp = openFile(filen_out, "w", 3);

    nr_chars = readXml(ifp);

    closeFile(ifp, 2);
    closeFile(ofp, 4);
    printf("Read %lu characters.\n", nr_chars);
    return 0;

}

line 60: The memory allocated here is destroyed by lines 75 and 80 -- memory leak.

I don't get what parser() is supposed to do.

This is a sightly modified version of readXml function compiled with VC++ 2010 Express on Windows 7. It does not contain the problem you reported. All I did was removed malloc(), there is no point allocating memory for only 4 bytes of data. Also simplified the if-else clause in that function.

#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#pragma warning(disable: 4996)
#define BUFSIZE 4


void error_handler(unsigned short int err) {
    char * error_desc;
    switch (err) {
        case 1: error_desc = "Input file could not be opened.\n";
            ;;
        case 2: error_desc = "Input file did not exist.\n";
            ;;
        case 3: error_desc = "Output file could not be opened\n";
            ;;
        case 4: error_desc = "Output file could not be closed.\n";
            ;;
        default: error_desc = "Unspecified error, aborting.\n";
            ;;
    }
    printf("Exiting with error %s\n", error_desc);
    exit(err);
}

FILE * openFile (char * filen_in, char * mode, unsigned short int err) {
    /* Open SAFT file.          */
    FILE * fp;
    if ((fp = fopen (filen_in, mode)) == NULL) {
        error_handler(err);
    }
    return fp;
}

void closeFile (FILE * fp, unsigned short int err) {
    /* Close output file.       */
    if (fclose(fp) != 0) {
        error_handler(err);
    }
}

char * parser(char ** p, unsigned int dif)
{
    /* Store first 2 chars of each string */
    /* printf("-------------- %d    %d  \n", p, *p);*/
    if (dif > 0) {
        ++*p;
    }
    return 0;
}

/* Reads SAFT-PT file and returns nr. of characters of xml file. */
unsigned long int readXml(FILE *f)
{
    int c;
    char ch;
    unsigned long int l = 0;                         /* Nr. of characters read.*/
    int i;
    char buffer[BUFSIZE + 1] = {0}; /* +1 for \0 */
    char * initial = buffer;
    char * to_save = 0;
    printf("*****   readXml   *****\n");

        /*printf("%c", ch); */
    /* After buffer == EOF, parse the remaining text. */
    i = 0;
    while ((c = getc(f)) != EOF) {
        ch = (char) c;
        ++l;

        if ( i == BUFSIZE ) {
            to_save = parser(& initial, i);  
            i = 0;
            memset(buffer,0,sizeof(buffer));
        }
        buffer[i++] = ch;
    }
    /* Parse the last characters. */
    to_save = parser(& initial, i);  

    printf("\n");
    return l;
}

int main() {

    FILE *ifp;
    FILE *ofp;
    char * filen_in = "a.xml";
    char * filen_out = "out.txt";

    unsigned long int nr_chars;
    ifp = openFile(filen_in, "r", 1);
    ofp = openFile(filen_out, "w", 3);

    nr_chars = readXml(ifp);

    closeFile(ifp, 2);
    closeFile(ofp, 4);
    printf("Read %lu characters.\n", nr_chars);
    return 0;

}

Edited 4 Years Ago by Ancient Dragon: add info

I receive a segfault when trying to close the second file (fclose(ofp))

This suggests that ofp might be NULL. If it turns out that you are unable to open the output file, perror() is likely to be helpful.

This article has been dead for over six months. Start a new discussion instead.