2017-08-15 68 views
0

我正在编写一个程序,给定一组输入和输出,计算出公式是什么。程序工作的方式是通过随机生成二叉树并通过遗传算法来确定哪一个是最好的。C函数返回指向垃圾内存的指针

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

在我使用两个结构,一个在二叉树中的节点和其他跟踪每个树是如何准确给出的数据(其健身)程序:

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

任何帮助将不胜感激。我一直在试图找出多天。

+0

你的调试器说什么 –

+0

当试图用node-> left或node-> right做任何事情时,“读取访问冲突” – Robbie

+3

'parents [0] =&parent1;':'parent1'是函数中的局部变量。 – BLUEPIXY

回答

4

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

您可以将parents初始化为struct node *而不是struct node **,并使其尺寸是struct node的两倍。然后,您可以将节点复制到数组中。这可以避免这个问题。或者,您可以将节点复制到堆上,以便返回struct node **。不过,你必须记得最终免费拷贝。