Search code examples
cmemoryfreeallocation

Different error messages while freeing allocated memory


I created a struct, called ArrayCount, that contains a double array and an integer that should count how often an array occurs.

If the size of the double-array is n, the idea is, to create an array of the struct ArrayCount of the size n! (n! is called m in my code).

The idea is to safe each permutation in the ArrayCount-array, counting the occurrences of each permutation, for a given algorithm. But that's just the background information and not part of the problem.

I am having issues while freeing the memory that was allocated for the double-Arrays. Oddly enough, ~ 1/10 times my code compiles without an error message and sometimes different error messages appear.

  1. error message:

    munmap_chunk(): invalid pointer
    Aborted (core dumped)
    
  2. error message:

    free(): invalid size
    Aborted (core dumped)
    
  3. error message:

    Segmentation fault (core dumped)
    

Part of the code:

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

What am I doing wrong?


Solution

  • I am having issues while freeing the memory that was allocated for the double-Arrays. Oddly enough, ~ 1/10 times my code compiles without an error message and sometimes different error messages appear.

    complies without error message or runs without error message? I see runtime errors ( Segfault or Abort signals, to be exact ) not compile time. kl

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

    The correct way to iterate through an array of m elements is

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

    As pointed out in the comments, offsets start at 0 and to to m-1, not m. That makes free(array_counts[i].array) becomes free(array_counts[m].array) What's at array_counts[m]? Could be various things, which might be deterministic or nondeterministic at runtime, but it is outside the memory you allocated. Behavior of free is undefined in this case, as it is whenever passed an address that wasn't allocated with malloc and friends.

    Consider http://man7.org/linux/man-pages/man3/malloc.3.html, a copy of the manpage for free:

    The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc(), or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs.