释放分配的内存时出现不同的错误消息

Different error messages while freeing allocated memory

我创建了一个名为 ArrayCount 的结构,它包含一个双精度数组和一个应该计算数组出现频率的整数。

如果双数组的大小是n,想法是,创建一个大小为n 的struct ArrayCount 的数组! (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;
}

我做错了什么?

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.

符合 没有错误消息或运行 没有错误消息?我看到运行时错误(确切地说是 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.htmlfree 的联机帮助页副本:

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.