двойное освобождение или повреждение при использовании char ** - PullRequest
0 голосов
/ 23 января 2019

Я выделяю память для моих int *occurrences int *wordCounts и char **uniqueWords указателей, а затем в конце функции, которая выделяет память, я освобождаю их. Однако, когда я компилирую программу, я получаю ошибку double free or corruption (!prev) aborting. Это вызвано malloc, free или это может быть связано с тем, как я инициализирую их внутри for loop?

PS: я говорю о sortedCount() методе, расположенном ближе к концу

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define MAX_STRING_SIZE 512 /* each line in the file can have up to 512 chars */

void populateWordsArray(int); 
void reverse(int);
void first(int);
void middle(int);
void last(int);
int count(int, char*, int);
void sortedCount(int);
void determineUniqueWords(int *,char **, int);
void *malloc_or_end(size_t);

void* malloc_or_end(size_t sz) {
  void *pointer;
  pointer = malloc(sz);
  if(pointer == NULL) {
    printf("Out of memory, terminating.\n");
    exit(-1);
  }
  return pointer;
}

/* turn into local */
FILE *file; 
char **wordList; 

void determineUniqueWords(int *occurrences, char **word, int N) {
    int i = 0;
    int j = 0;
    for(i = 0; i < N; i++) {

        if(occurrences[i] < 1) {
            continue;
        }

        for(j = i + 1; j < N; j++) {
            if(occurrences[j] == 1 && (strcmp(word[i],word[j])) == 0) {
                occurrences[i]++;
                occurrences[j] = 0;
            }
        }
    }
}

/**
 * Function populateWordsArray: reads N words from
 * the given file and populates the wordList array with them.
 * Has one argument: int N - the number of words to read. 
 * */
void populateWordsArray(int N) {
    int i = 0;

    while(i < N && (fscanf(file,"%s",wordList[i]) == 1)) { /* fscanf returns the number of successfully read items. If it's not 1, the read failed. Same as checking if fscanf reads the eof char. */
        i++;
    }
}

/**
 * Function reverse: prints the words of the
 * text file in reverse order.
 * */
void reverse(int N) {
    int i = 0;
    for(i = N-1; i >= 0; i--) {
        if(i == 0) {
            printf("%s \n",wordList[i]);
        } else if(strcmp(wordList[i],"") == 0) { /* improve this in main-> memory allocation */
            continue;
        }else {
            printf("%s ",wordList[i]);
        }
    }
    return;
}

/**
 * Function first: Prints the first char of each
 * word in the file.
 * */
void first(int N) {
    char firstChar;
    int i = 0;

    for(i = 0; i < N; i++) {
        firstChar = *wordList[i];
        printf("%c",firstChar);
    }
    printf("\n");
    return;
}

/**
 * Function middle: Prints the middle char of each word
 * from the given file.
 * */
void middle(int N) {
    int middleIndex = 0;
    int i = 0;
    char midChar;

    for(i = 0; i < N; i++) {
        if((strlen(wordList[i]) % 2) == 0) { /* artios */
            middleIndex = ((strlen(wordList[i]) / 2) - 1);
            midChar = wordList[i][middleIndex];
        }
        else { /* peritos */
            middleIndex = (int) ceil((strlen(wordList[i]) / 2));
            midChar = wordList[i][middleIndex];
        }
        printf("%c",midChar);
    }
    printf("\n");
    return;
}

/**
 * Function last: Prints the last char of each
 * word from the given file.
 * */
void last(int N) {
    int i = 0;
    char lastChar;
    int lastPos;

    for(i = 0; i < N; i++) {
        lastPos = strlen(wordList[i]) - 1;
        lastChar = wordList[i][lastPos];
        printf("%c",lastChar);
    }
    printf("\n");
    return;
}

/**
 * Function count: Prints the number of times
 * that the selected word is found inside the N first words
 * of the file.
 * */
int count(int N, char *word, int callID) {
    int i = 0;
    int count = 0;
    for(i = 0; i < N; i++) {
        if(strcmp(word,wordList[i]) == 0) {
            count++;
        }
    }
    if(callID == 0) { /* if callID == 0 (main called count and we want the output) */
        printf("%d",count);
        printf("\n");
    }
    return count;
}

void sortedCount(int N) {
    int i,j = 0;
    int *occurrences;
    int *wordCounts;
    char **uniqueWords;

    /* mem allocation */
    uniqueWords = malloc_or_end(N * sizeof(char*)); /* worst case: every word is unique */
    wordCounts = malloc_or_end(N * sizeof(int));
    occurrences = malloc_or_end(N * sizeof(int));

    /* initialize rootWord and occurrences for the "each word is unique and occurs only once" scenario */
    for(i = 0; i < N; i++) {
        uniqueWords[i] = malloc_or_end(MAX_STRING_SIZE * sizeof(char));
        occurrences[i] = 1;
    }

    determineUniqueWords(occurrences,wordList,N);

    /* populate the wordCounts & uniqueWords "arrays" with the appropriate data in order to sort them successfully */
    for(i = 0; i < N; i++) {
        if(occurrences[i] > 0) {
            wordCounts[i] = count(N,wordList[i],1);
            uniqueWords[i] = wordList[i];
        }
    }

    for(i = 0; i < N; i++) {
        free(uniqueWords[i]);
    }
    free(uniqueWords);
    free(occurrences);
    free(wordCounts);
    return;
}

int main(int argc,char *argv[]) { /* argv[1] = op argv[2] = name argv[3] = <word> */
    int N = -1;
    int i = 0;
    int spaceNum,nlNum = -1;


    file = fopen(argv[2],"r");

    if(file == (FILE *) NULL) { /* check if the file opened successfully */
        fprintf(stderr,"Cannot open file\n");
    }

    fscanf(file,"%d",&N); /* get the N number */

    wordList = malloc_or_end(N * sizeof(char *)); /* allocate memory for pointers */

    for(i = 0; i < N; i++) {
        wordList[i] = malloc_or_end(MAX_STRING_SIZE * sizeof(char)); /* allocate memory for strings */
    }

    populateWordsArray(N);

    if(strcmp(argv[1],"-reverse") == 0) {
        reverse(N);
    } else if(strcmp(argv[1],"-first") == 0) {
        first(N);
    } else if(strcmp(argv[1],"-middle") == 0) {
        middle(N);
    } else if(strcmp(argv[1],"-last") == 0) {
        last(N);
    } else if((strcmp(argv[1],"-count") == 0) && argv[3] != NULL) {
        i = count(N,argv[3],0);
    } else if((strcmp(argv[1],"-sorted") == 0) && (strcmp(argv[3],"-count") == 0)) {
        sortedCount(N);
    } else {
        /* i only wish i could print something here */
    }


    /* End of program operations */
    for(i = 0; i < N; i++) {
        free(wordList[i]);
    }
    free(wordList);
    fclose(file);
    return 0;
}

1 Ответ

0 голосов
/ 23 января 2019

Вы перезаписываете значение указателя на память кучи в строке 185:

uniqueWords[i] = wordList[i];

Это означает, что когда вы free это позже, вы фактически освобождаете выделенные строки в wordList. Теперь у вас есть две проблемы:

  1. Когда вы освобождаете строки wordList в строках 244-246, это будет двойное значение
  2. Вы теряете ссылку на строки uniqueWords.

Используйте strcpy для назначения динамически размещаемой строки вместо операции =.

...