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

C Function returning pointer to garbage memory

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

我编写的所有函数都可以单独工作,但有一个或两个不能。

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

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

然后是函数,它本质上是程序的主要部分。此函数循环遍历种群,随机修改它们并在多代中选择其中最好的。由此,它选择最佳个体(最高适应度)并 returns 它。具体如下:

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 函数 returns 指向一个充满垃圾值的个体的指针。为了缩小原因范围,我开始注释掉代码。通过注释掉 subtree_crossover() 或 generational_replacement() 函数 returns 一个有效的个体。基于此,我猜测错误是由 subtree_crossover() 或 generational_replacement() 引起的。

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

如有任何帮助,我们将不胜感激。我已经想了好几天了。

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

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