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

时间:2018-12-20 20:51:22

标签: c memory free allocation

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

如果双精度数组的大小为n,则想法是创建大小为n的struct ArrayCount的数组! (n!在我的代码中称为m)。

这个想法是为了保护给定算法的ArrayCount-array中的每个排列,计算每个排列的出现次数。但这只是背景信息,而不是问题的一部分。

在释放为双数组分配的内存时遇到问题。 奇怪的是,我的代码的编译次数是〜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 :(得分:1)

  

我在释放分配给内存的内存时遇到问题   双数组。奇怪的是,〜1/10倍我的代码编译没有   错误消息,有时还会显示不同的错误消息。

符合而没有错误消息或运行而没有错误消息?我看到运行时错误(准确地说是Segfault或Abort信号)没有编译时。

 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)          之前,会发生未定义的行为。