C函数返回指向垃圾内存的指针

时间:2017-08-15 21:55:29

标签: c pointers binary-tree genetic-programming

我正在编写一个程序,给定一组输入和输出,计算出等式是什么。程序的工作方式是随机生成二叉树并将它们通过遗传算法来查看哪个是最好的。

我写的所有功能都是单独工作的,但有一两个功能没有。

在程序中我使用两个结构,一个用于二叉树中的节点,另一个用于跟踪每棵树给出数据的准确度(它的适应性):

struct node {
    char value; 
    struct node *left, *right;
};

struct individual {
    struct node *genome;
    double fitness;
};

我用来随机创建树的一个函数是一个子树交叉函数,它随机合并两棵树,返回两棵树,它们是彼此混合的。功能如下:

struct node **subtree_crossover(struct node parent1, struct node parent2) {
    struct node *xo_nodes[2];

    for (int i = 0; i < 2; i++) {
        struct node *parent = (i ? &parent2 : &parent1);

        // Find the subtree at the crossover point
        xo_nodes[i] = get_node_at_index(&parent, random_index);
    }

    else {
        // Swap the nodes
        struct node tmp = *xo_nodes[0];

        *xo_nodes[0] = *xo_nodes[1];
        *xo_nodes[1] = tmp;

    }

    struct node **parents = malloc(sizeof(struct node *) * 2);
    parents[0] = &parent1;
    parents[1] = &parent2;

    return parents;
}

另一个函数使用一个需要两个群体(个体列表)并从两者中选择最佳群体,返回下一个群体。它如下:

struct individual *generational_replacement(struct individual *new_population,
    int size, struct individual *old_population) {

    int elite_size = 3;

    struct individual *population = malloc(sizeof(struct individual) * (elite_size + size));

    int i;

    for (i = 0; i < size; i++) {
        population[i] = new_population[i];
    }

    for (i; i < elite_size; i++) {
        population[i] = old_population[i];
    }

    sort_population(population);

    population = realloc(population, sizeof(struct individual) * size);

    return population;
}

然后有一个功能基本上是程序的主要部分。这个函数循环遍历一个群体,随机修改它们并在多代中选择其中最好的。从中,它选择最佳个体(最高适应度)并返回它。它如下:

struct individual *search_loop(struct individual *population) {

    int pop_size = 10;
    int tourn_size = 3;
    int new_pop_i = 0;
    int generation = 1

    struct individual *new_population = malloc(sizeof(struct individual) * pop_size);

    while (generation < 10) {
        while (new_pop_i < pop_size) {

            // Insert code where random subtrees are chosen

            struct node **nodes = subtree_crossover(random_subtree_1, random_subtree_2);

            // Insert code to add the trees to new_population
        }

        population = generational_replacement(new_population, pop_size, population);

        // Insert code to sort population by fitness value
    }

    return &population[0];
}

我遇到的问题是search_loop函数返回一个指向充满垃圾值的个人的指针。为了缩小原因,我开始评论代码。通过注释掉subtree_crossover()或generational_replacement(),函数返回一个有效的个体。基于此,我的猜测是错误是由subtree_crossover()或generational_replacement()引起的。

显然,这是我正在使用的代码的大幅减少版本,但我相信它仍然会显示我得到的错误。如果您想查看完整的源代码,请查看该项目的开发分支:https://github.com/dyingpie1/pony_gp_c/tree/Development

非常感谢任何帮助。我一直试图解决这个问题多天。

1 个答案:

答案 0 :(得分:4)

您的subtree_crossover()函数将两个节点作为值。该函数将接收副本,然后这些副本将存在于堆栈中,直到函数退出,此时它们将变为无效。不幸的是,该函数稍后将其地址粘贴到它返回的数组中。因此,subtree_crossover()的结果将包含两个指向垃圾数据的无效指针。

您可以将parents初始化为struct node *而不是struct node **,并使其大小为struct node的两倍。然后,您可以将节点复制到数组中。这样可以避免这个问题。或者,您可以将节点复制到堆上,以便返回struct node **。然后,你必须记住最终释放副本。