【问题标题】:Different error messages while freeing allocated memory释放分配的内存时出现不同的错误消息
【发布时间】:2019-05-21 09:33:58
【问题描述】:

我创建了一个名为 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;
}

我做错了什么?

【问题讨论】:

  • 你能创建一个以同样方式崩溃的更最小示例吗?
  • 数组索引从0开始。如果为array_counts 分配m 元素计数,则无法使用i=m 访问array_counts[i]
  • 与您的问题描述无关:您对srand() 的使用是错误的。放入main();不要在循环中调用srand()
  • calloc(n, 8); 幻数 8 看起来很可疑。
  • array_copy() 没用;如果您要交换两个索引的值,只需将一个保存在临时 double 中,而不是复制整个数组。这将删除至少 1000 次对 calloc()free() 的调用。

标签: c memory free allocation


【解决方案1】:

我在释放分配给 双数组。奇怪的是,大约 1/10 次我的代码在没有 错误消息,有时会出现不同的错误消息。

complies 没有错误消息或 runs 没有错误消息?我看到运行时错误(确切地说是 Segfault 或 Abort 信号)不是编译时间。 kl

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

遍历m元素数组的正确方法是

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

正如 cmets 中所指出的,偏移量从 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 的联机帮助页副本:

free() 函数释放 ptr 指向的内存空间, 必须由先前调用 malloc()、calloc() 或 重新分配()。否则,或者如果 free(ptr) 已经被调用 之前,会发生未定义的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2017-03-22
    • 2016-05-08
    • 2014-04-02
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多