C free()无效下一个大小(正常)

时间:2014-02-05 00:17:44

标签: c free

我对C很新,我似乎无法弄清楚什么似乎是一个非常简单的指针问题。我的程序将行号添加到文件中。它逐行读入文件,然后在每行的开头添加一个行号。它可以单独在每个文件上正常工作,如下所示:

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$

但是当我一起运行它时,我得到了上述错误。以下代码是我的程序。

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++;
    }
}

我已将问题缩小到lineNumPtr。在第二个文件之后释放lineNumPtr时发生错误。如果没有释放lineNumPtr,我知道编程错误,程序运行正常。

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;
}

我道歉了。这是我的第一篇文章,我想确保我为你们提供了足够的信息,以便给我最好的答案。谢谢你的任何和所有答案。他们非常感兴趣。

2 个答案:

答案 0 :(得分:1)

好的,伙计们,所以我已经让它上班了。我已经调整了lineNumAdder.c文件。该程序现在每次读入时都会增加numberedFile的大小。此外,第二个文件中出现错误,因为当我strcat进入malloced区域时,行号已经是{存储在那里,所以numberedFile会溢出。我已使用calloc代替malloc修复此问题。感谢所有给出答案并评论的人。他们都帮助很大。

这是完成的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, 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;
}

答案 1 :(得分:0)

所以,很难调试这个...但至少:

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

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

    return i;
}