2017-08-15 10 views
0

私は、入力と出力のセットが与えられると、方程式が何であるか把握するプログラムを書いています。プログラムの仕組みは、無作為にバイナリツリーを生成し、それを遺伝的アルゴリズムに入れて、どれが最良かを調べることです。Cガベージメモリへのポインタを返す関数

私が書いたすべての機能は個別に動作しますが、1つまたは2つはありません。

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

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

一つ関数I:Iは各ツリーはデータ(その適応度)が与えられた方法正確を追跡するために、2つの構造体、二分木におけるノードの一方及び他方を使用するプログラムで

ツリーをランダムに作成するための使用は、サブツリーのクロスオーバー関数です。これは、2つのツリーをランダムにマージし、互いに混在する2つのツリーを返します。次のように関数は次のとおりです。

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

別の機能は、次の人口を返し、2つの集団(個人のリスト)を取り、両方から最善の選択1を使用しました。

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

ノード→左またはノード→右のいずれかで何かしようとすると「読み取りアクセス違反」 – Robbie

+3

'parents [0] =&parent1;':parent1'は関数内のローカル変数です。 – BLUEPIXY

答えて

4

subtree_crossover()関数は2つのノードを値として取ります。この関数はコピーを受け取り、関数が終了するまでスタック上に存続します。その時点で、それらは無効になります。残念なことに、この関数は後でそれらのアドレスを返す配列に貼り付けます。したがって、subtree_crossover()の結果には、2つのガベージ・データへの無効なポインタが含まれます。

struct node **の代わりにparentsstruct node *として初期化し、struct nodeの2倍にすることができます。次に、ノードを配列にコピーするだけです。これは問題を回避するでしょう。あるいは、ノードをヒープにコピーすると、struct node **を返すことができます。しかし、あなたは最終的にコピーを解放することを覚えておく必要があります。

関連する問題