Различные сообщения об ошибках при освобождении выделенной памяти - PullRequest
0 голосов
/ 20 декабря 2018

Я создал структуру с именем ArrayCount, которая содержит двойной массив и целое число, которое должно подсчитывать, как часто встречается массив.

Если размер двойного массива равен n, идея состоит в том, чтобысоздать массив структуры ArrayCount размером n!(в моем коде n! называется m).

Идея состоит в том, чтобы сохранить каждую перестановку в массиве ArrayCount, считая случаи каждой перестановки, для данного алгоритма.Но это только справочная информация, а не часть проблемы.

У меня возникают проблемы при освобождении памяти, выделенной для двойных массивов.Как ни странно, ~ 1/10 раз мой код компилируется без сообщения об ошибке, и иногда появляются различные сообщения об ошибках.

  1. сообщение об ошибке:

    munmap_chunk(): invalid pointer
    Aborted (core dumped)
    
  2. сообщение об ошибке:

    free(): invalid size
    Aborted (core dumped)
    
  3. сообщение об ошибке:

    Segmentation fault (core dumped)
    

Часть кода:

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

double* array_copy(const double* a, int n) {
    srand(time(NULL));

    double* copy = calloc(n, 8);
    for(int i = 0; i < n; i++) {
        copy[i] = a[i];
    }
    return copy;
}

void shuffle(double* a, int n) {
    for(int i = n - 1; i >= 0; i--) {
        time_t t;
        /* Intializes random number generator */
        srand((unsigned) time(&t));

        double* copy = array_copy(a, i + 1);
        //Generates random numbers in the closed intervall [0,i].
        int random = rand() % (i + 1);

        a[i] = a[random];
        a[random] = copy[i];

        free(copy);
    }
}

// Refers to a double array and counts how often this array has 
occurred yet.
typedef struct {
    double* array;
    int counter;
} ArrayCount;

// Computes the factorial of n: n!.
int factorial(int n) {
    int result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

/*
Saves all permutations in array_counts, for a given double array of 
the length n and counts how often each permutations occurs.
(Hint given by our supervisor: Save a copy of a in array_counts)
*/
void update_array_counts(/*INOUT*/ ArrayCount* array_counts, int m, 
/*IN*/ const double* a, int n) {
    double* copy_a = array_copy(a, n);

    //Increases the counter by 1, if a is already listed in 
array_counts
for(int i = 1; i <= m; i++) {
    int count = 0;
    for(int j = 0; j < n; j++) {
        if(array_counts[i].array[j] == a[j]) count++;
    }
    if(count == n) {
        array_counts[i].counter++;
        free(copy_a);
        return;
    }
}

//Saves a in array_counts and sets the counter to 1, if a is not 
listed in array_counts, yet
    for(int i = 1; i <= m; i++) {
        int count = 0;
        for(int j = 0; j < n; j++) {
            if(array_counts[i].array[j] == 0) count++;
        }
        if(count == n) {
            for(int j = 0; j < n; j++) {
                array_counts[i].array[j] = a[j];
            }
            array_counts[i].counter = 1;
            free(copy_a);
            return;
        }
    }   
}

// Gibt die Häufigkeit der verschiedenen Permutationen eines Arrays 
der Länge n aus.
void shuffle_frequency(int n) {
    double a[n];
    for (int i = 0; i < n; i++) {
        a[i] = i; 
    }
    int m = factorial(n);
    ArrayCount* array_counts = calloc(m, sizeof(ArrayCount));
    for(int i = 1; i <= m; i++){
        array_counts[i].array = calloc(n, sizeof(double));
    }
    for (int i = 0; i < 1000 * m; i++) {
        shuffle(a, n);
        update_array_counts(array_counts, m, a, n);
    }
    for (int i = 1; i <= m; i++) {
        printf("%4d%8d    ", i, array_counts[i].counter);
    }
    //The next free-statement is causing problems.
    for(int i = 1; i <= m; i++) {
        printf("i = %d\n", i);
        free(array_counts[i].array);
    }

    free(array_counts);
}



int main(void) {
    shuffle_frequency(4);

    return 0;
}

Что я делаю не так?

1 Ответ

0 голосов
/ 21 декабря 2018

У меня проблемы при освобождении памяти, выделенной для двойного массива.Как ни странно, ~ 1/10 раз мой код компилируется без сообщения об ошибке, и иногда появляются различные сообщения об ошибках.

соответствует без сообщения об ошибке или работает безсообщение об ошибке?Я вижу ошибки времени выполнения (точнее, сигналы Segfault или Abort), а не время компиляции.kl

 for (int i = 1; i <= m; i++) {

Правильный способ перебора массива элементов m -

 for(int i=0; i < m; i++){

Как указано в комментариях, смещения начинаются с 0 и до m-1, а не m.Это делает free(array_counts[i].array) становится free(array_counts[m].array) Что на array_counts[m]?Это могут быть разные вещи, которые могут быть детерминированными или недетерминированными во время выполнения, но они находятся за пределами выделенной памяти.Поведение free в этом случае не определено, так как каждый раз, когда передается адрес, который не был выделен malloc и друзьям.

Рассмотрим http://man7.org/linux/man-pages/man3/malloc.3.html, копию справочной страницы для free:

Функция free () освобождает пространство памяти, на которое указывает ptr, что должно бытьвозвращается предыдущим вызовом malloc (), calloc () или realloc ().В противном случае или, если free (ptr) уже был вызван ранее, происходит неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...