Question

I'm fairly new to C and I can't seem to figure out what seems to be a pretty simple pointer problem. My program adds line numbers to a file. It reads in the file line by line and then adds a line number to the beginning of each line. It works fine on each file individually as you can see below:

soccer@soccer-Dell-DV051:~/code C$ ./a.out test.c
soccer@soccer-Dell-DV051:~/code C$ ./a.out miscellaneousHeader.h
soccer@soccer-Dell-DV051:~/code C$ ./a.out test.c miscellaneousHeader.h
*** Error in `./a.out': free(): invalid next size (normal): 0x08648170 ***
Segmentation fault (core dumped)
soccer@soccer-Dell-DV051:~/code C$

but when I run them together I get the above error. The following code is my program.

Compiler.c:

#include <stdio.h>
#include "lineNumAdderHeader.h"
#include "miscellaneousHeader.h"

int main(int argc, char *argv[]){
    if (argc < 2)
        fatal("in main(). Invalid number of arguments");

    int i = 1;
    while (i < argc){
        lineNumAdder(argv[i]);
        i++;
    }
}

I have narrowed the problem to the lineNumPtr. The error occurs when lineNumPtr is freed after the second file. If lineNumPtr is not freed, which I know is bad programming, the program works just fine.

lineNumAdder.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miscellaneousHeader.h"
#include "lineNumAdderHeader.h"

int lineSizeChecker(FILE*, int);
int lineNumChecker(char*);
int fileSizeChecker(FILE*);


void lineNumAdder(char* filename){
    int lineSpace, position, lineNumCheckerBoolean, numOfDigits, fileSpace;
    int lineNum = 1;
    char *lineNumPtr = NULL;
    char *numberedFile = NULL;
    char *nonNumberedLine = NULL;
    char *originalLine = NULL;
    FILE *file = errorCheckedFopen(filename, "r+w");

    while(1){
        position = ftell(file);

        if (position == 0){
            fileSpace = fileSizeChecker(file);
            numberedFile = errorCheckedMalloc(fileSpace);
        }

        lineSpace = lineSizeChecker(file, position);
        if (position == 0)
            originalLine = errorCheckedMalloc(lineSpace);
        else
            originalLine = realloc(originalLine, lineSpace);

        if (fgets(originalLine, lineSpace, file) == NULL)
            break;

        lineNumCheckerBoolean = lineNumChecker(originalLine);

        if (lineNumCheckerBoolean == 0){
            if (position == 0)
                nonNumberedLine = errorCheckedMalloc(lineSpace - 9);
            else
                nonNumberedLine = realloc(nonNumberedLine, lineSpace - 9);

            strcpy(nonNumberedLine, &originalLine[9]);
        }
        else{
            if (position == 0)
                nonNumberedLine = errorCheckedMalloc(lineSpace);
            else
                nonNumberedLine = realloc(nonNumberedLine, lineSpace);

            strcpy(nonNumberedLine, originalLine);

            fileSpace += 8;
            numberedFile = realloc(numberedFile, fileSpace);
        }

        numOfDigits = intDigitFinder(lineNum);
        if (position == 0)
            lineNumPtr = errorCheckedMalloc(numOfDigits);
        else
            lineNumPtr = realloc(lineNumPtr, numOfDigits);
        sprintf(lineNumPtr, "%d", lineNum);

        strcat(numberedFile, "/*");
        strcat(numberedFile, lineNumPtr);
        strcat(numberedFile, "*/");
        if (lineNum < 10)
            strcat(numberedFile, "    ");
        else if (lineNum >= 10 && lineNum < 100)
            strcat(numberedFile, "   ");
        else if (lineNum >= 100 && lineNum < 1000)
            strcat(numberedFile, "  ");
        else if (lineNum >= 1000 && lineNum < 10000)
            strcat(numberedFile, " ");
        strcat(numberedFile, nonNumberedLine);
        lineNum++;
    }

    fclose(file);
    free(originalLine);
    free(nonNumberedLine);
    free(lineNumPtr);
    free(numberedFile);
}

int lineNumChecker(char *comment){
    if (sizeOf(comment) < 8)
        return 1;

    if (comment[7] == '/' || comment[6] == '/' || comment[5] == '/' || comment[4] == '/')
        return 0;
    else
        return 1;
}

int lineSizeChecker(FILE *file, int position){
    int i = 2;
    int ch;

    while ((ch = fgetc(file)) != '\n' && ch != EOF)
        i++;

    fseek(file, position, SEEK_SET);

    return i;
}

int fileSizeChecker(FILE *file){
    int i = 2;

    while (fgetc(file) != EOF)
        i++;

    fseek(file, 0, SEEK_SET);

    return i;
}

miscellaneous.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miscellaneousHeader.h"

void fatal(char*);

int sizeOf(char *data){
    int i = 1;

    while(data[i-1] != '\n')
        i++;

    return i;
}

void *errorCheckedMalloc(size_t size){
    void *ptr = malloc(size);

    if (ptr == NULL)
        fatal("in errorCheckedMalloc(). Memory Allocation Failure\n");
    else
        return ptr;
}

FILE *errorCheckedFopen(char *filename, char *mode){
    FILE *file = fopen(filename, mode);

    if (file == NULL)
        fatal("in errorCheckedFopen(). File Opening Failure\n");
    else
        return file;
}

void fatal(char *errorMessage){
    char* completedErrorMessage = errorCheckedMalloc(sizeOf(errorMessage)+17);

    strcpy(completedErrorMessage, "[!!] Fatal Error ");
    strcat(completedErrorMessage, errorMessage);

    perror(completedErrorMessage);

    free(completedErrorMessage);

    exit(-1);
}

int intDigitFinder(int num){
    int digits = 0;

    do {
        num /= 10;
        digits++;
    } while (num != 0);

    return digits;
}

void *reMalloc(void *ptr, size_t size){
    char buf[strlen(ptr) + 1];
    strcpy(buf, ptr);

    free(ptr);

    ptr = errorCheckedMalloc(size);

    if(size >= strlen(buf))
        strcpy(ptr, buf);

    return ptr;
}

I apologize for the length. This is my first post and I wanted to make sure that I provided enough information for you guys to give me the best answers possible. Thank you for any and all answers. They are much appriciated.

Was it helpful?

Solution

Ok guys, so I have gotten it to work. I have tweaked the lineNumAdder.c file. The program now increases numberedFile's size by the line each time it is read in. Also the error was occuring on the second file because when I would strcat the line number into the malloced area junk was already stored there, so numberedFile would overflow. I have fixed this by using calloc instead of malloc. Thank you to all who gave answers and commented. They all helped tremendously.

Here is the completed lineNumAdder.c file:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miscellaneousHeader.h"
#include "lineNumAdderHeader.h"

int lineSizeChecker(FILE*, int);
int lineNumChecker(char*);
int fileSizeChecker(FILE*);


void lineNumAdder(char* filename){
    int lineSpace, filePosition, lineNumCheckerBoolean, numOfDigits;
    int fileSpace = 0;
    int lineNum = 1;
    char *lineNumPtr = NULL;
    char *numberedFile = NULL;
    char *nonNumberedLine = NULL;
    char *originalLine = NULL;
    FILE *file = errorCheckedFopen(filename, "r+w");

    while(1){
        filePosition = ftell(file);

        lineSpace = lineSizeChecker(file, filePosition);
        if (filePosition == 0)
            originalLine = calloc(1, lineSpace);
        else
            originalLine = realloc(originalLine, lineSpace);

        if (fgets(originalLine, lineSpace, file) == NULL)
            break;

        lineNumCheckerBoolean = lineNumChecker(originalLine);
        if (lineNumCheckerBoolean == 0){
            fileSpace += lineSpace;
            if (filePosition == 0){
                nonNumberedLine = calloc(1, lineSpace - 8);

                numberedFile = calloc(1, fileSpace);
            }
            else{
                nonNumberedLine = realloc(nonNumberedLine, lineSpace - 8);

                numberedFile = realloc(numberedFile, fileSpace);
            }

            strcpy(nonNumberedLine, &originalLine[9]);
        }
        else{
            fileSpace += lineSpace + 9;
            if (filePosition == 0){
                nonNumberedLine = calloc(1, lineSpace);

                numberedFile = calloc(1, fileSpace);
            }
            else{
                nonNumberedLine = realloc(nonNumberedLine, lineSpace);

                numberedFile = realloc(numberedFile, fileSpace);
            }

            strcpy(nonNumberedLine, originalLine);
        }

        numOfDigits = intDigitFinder(lineNum);
        if(filePosition == 0)
            lineNumPtr = calloc(1, numOfDigits);
        else
            lineNumPtr = realloc(lineNumPtr, numOfDigits);
        sprintf(lineNumPtr, "%d", lineNum);

        strcat(numberedFile, "/*");
        strcat(numberedFile, lineNumPtr);
        strcat(numberedFile, "*/");
        if (lineNum < 10)
            strcat(numberedFile, "    ");
        else if (lineNum >= 10 && lineNum < 100)
            strcat(numberedFile, "   ");
        else if (lineNum >= 100 && lineNum < 1000)
            strcat(numberedFile, "  ");
        else if (lineNum >= 1000 && lineNum < 10000)
            strcat(numberedFile, " ");
        strcat(numberedFile, nonNumberedLine);
        lineNum++;
    }

    fclose(file);
    free(originalLine);
    free(nonNumberedLine);
    free(lineNumPtr);
    free(numberedFile);
}

int lineNumChecker(char *comment){
    if (sizeOf(comment) < 8)
        return 1;

    if (comment[7] == '/' || comment[6] == '/' || comment[5] == '/' || comment[4] == '/')
        return 0;
    else
        return 1;
 }

 int lineSizeChecker(FILE *file, int position){
    int i = 2;
    int ch;

    while ((ch = fgetc(file)) != '\n' && ch != EOF)
        i++;

    fseek(file, position, SEEK_SET);

    return i;
}

int fileSizeChecker(FILE *file){
    int i = 2;

    while (fgetc(file) != EOF)
        i++;

fseek(file, 0, SEEK_SET);

    return i;
}

OTHER TIPS

So, it's difficult to debug this... But at the very least:

int sizeOf(char *data) {
    int i = 1;

    while(data[i-1] != '\n' && data[i-1] != '\0')
        i++;

    return i;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top