2017-12-25 21 views
-1

私は赤黒の木の上にセットを実装しようとしています。私はセグメンテーション違反を得る比較機能にアクセスしようとするたびに構造体の関数にアクセスするときのsegfault

typedef struct rb_tree { 
int (*compare)(const void* a, const void* b); 
void (*destroy_key)(void* a); 
void (*destroy_info)(void* a); 
void (*print_key)(const void* a); 
void (*print_info)(void* a); 
rb_node* root;    
rb_node* nil;    
} rb_tree; 

:私のツリーは、以下の構造体で定義されています。例えば、このヘルパー関数のif文での比較において:

void tree_insert_help(rb_tree* tree, rb_node* z) { 
rb_node* x; 
rb_node* y; 
rb_node* nil = tree->nil; 

z->left = z->right = nil; 
y = tree->root; 
x = tree->root->left; 
while(x != nil) { 
    y = x; 
    if (1 == tree->compare(x->key, z->key)) { /* x.key > z.key */ 
     x = x->left; 
    } else { /* x,key < = z.key */ 
     x = x->right; 
    } 
} 
z->parent = y; 
if ((y == tree->root) || (1 == tree->compare(y->key, z->key))) { /* y.key > z.key */ 
    y->left = z; 
} else { 
    y->right = z; 
} 
} 

これは私がテストするために使用していますとのセグメンテーションフォルトを取得していますコードです。それはTREE->比較呼び出して以来、私はset.h

#include "set.h" 
#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char* argv[]) {; 

int int_comp(const void* a,const void* b) { 
    if(*(int*)a > *(int*)b) return(1); 
    if(*(int*)a < *(int*)b) return(-1); 
    return(0); 
} 
    void dfunc(void * a){ 
     free((int*)a); 
    } 
    void dinfo(void* a){ 
     ; 
    } 
    void print_int(int* a){ 
     printf("%d",*a); 
    } 
    set seta = new_set(int_comp, dfunc, dinfo, print_int, null_function); 
    int x = 10; 
    int y = 9; 
    int z = 12; 
    insert_element(seta, &x); 
    insert_element(seta, &y); 
    insert_element(seta, &z); 
    print_set(seta); 
} 

typedef struct rb_tree *set; 
typedef struct rb_node *element; 

を持っているこのコードは、2番目の挿入に失敗することに注意してください。 GDBを使用してスタックトレースを行うと、次のようになります。

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffffffde1b8 in ??() 
(gdb) bt 
#0 0x00007ffffffde1b8 in ??() 
#1 0x0000000000400ce1 in TreeInsertHelp (tree=0x604010, z=0x604360) at red_black_tree.c:185 
#2 0x0000000000400dce in RBTreeInsert (tree=0x604010, key=0x7ffffffde160, info=0x604340) at red_black_tree.c:233 
#3 0x000000000040096b in insert_element (seta=0x604010, key=0x7ffffffde160) at set.c:22 
#4 0x0000000000400848 in main (argc=1, argv=0x7ffffffde2c8) at test.c:38 

さらに、実際にはvalgrindでは完全に正常に動作します。私が構造体で関数を使用したのはこれが初めてです。私はこの問題を他の場所で検索しようとしており、デバッグをほとんど進めていません。ツリー構造のcompare関数にアクセスしようとするとsegfaultが発生するのはなぜですか?

編集: 新しいセットは、新しいツリーを作成する次の関数のラッパーです。

rb_tree* rb_tree_create(int (*comp_func) (const void*, const void*), 
       void (*dest_func) (void*), 
       void (*info_dest_func) (void*), 
       void (*print_func) (const void*), 
       void (*print_info)(void*)) { 
rb_tree* new_tree; 
rb_node* temp; 

new_tree = (rb_tree*) safe_malloc(sizeof(rb_tree)); 
new_tree->compare = comp_func; 
new_tree->destroy_key = dest_func; 
new_tree->print_key = print_func; 
new_tree->print_info = print_info; 
new_tree->destroy_info = info_dest_func; 

temp = (rb_node*) safe_malloc(sizeof(rb_node)); 
new_tree->nil = temp; 
temp->parent = temp; 
temp->left = temp; 
temp->right = temp; 
temp->red = 0; 
temp->key = 0; 
temp = (rb_node*) safe_malloc(sizeof(rb_node)); 
new_tree->root = temp; 
temp->parent = new_tree->nil; 
temp->left = new_tree->nil; 
temp->right = new_tree->nil; 
temp->key = 0; 
temp->red = 0; 
return(new_tree); 
} 

EDIT 2: 私は私の問題を解決しました。 new_setへのポインタを渡していた関数は、main関数内で定義されていました。私が主な機能の外にそれらを移動したとき、それはsegfaultingを止めました。

+1

':あなたの "new_set" 機能で

あなたはこのような何かを行う必要があります。また、これは[mcve] – coderredoc

+0

ではありません*コードをインデントし、コード全体にわたって一貫して[インデントスタイル](https://en.wikipedia.org/wiki/Indent_style)を使用してください。そうすることで**読みやすく/管理しやすくなります**。 Stack Overflowに配置したコードでは、ユーザーが投稿を優先して投票する可能性が高くなり、人々はあなたの質問に答える時間がかかります。どのスタイルを選択するかは実際問題ではありません(一部の言語では、他のスタイルよりも適切なスタイルがいくつかあります)。しかし、*単一のプロジェクトのすべてのコードに対して、* 1つを選んで一貫して使用する*。 – Makyen

答えて

1

あなたは構造体を作成しました。 "compare"は関数へのポインタです。しかし、どこにも向いていません。 "new_set"関数で設定する必要がありますが、表示していません。それを示してnew_set`

... // new_set_struct is a struct that you've created and returning from new_set function 
new_set_struct->compare = &int_comp; 
... // all other new_set_struct initial configuration is following 
return new_set_struct; 
+0

ありがとう、私は質問にnew_setを含めるべきだと思っていたはずです。関数へのポインタを設定するときに、&を使用する必要がありますか?私は、関数のために以下のものが同等であったという印象を受けました:new_set_struct-> compare =&int_comp;およびnew_set_struct-> compare = int_comp; – user3210228

+0

@ user3210228:はい。これは同等です。 – coderredoc

関連する問題