私は赤黒の木の上にセットを実装しようとしています。私はセグメンテーション違反を得る比較機能にアクセスしようとするたびに構造体の関数にアクセスするときの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を止めました。
':あなたの "new_set" 機能で
あなたはこのような何かを行う必要があります。また、これは[mcve] – coderredoc
ではありません*コードをインデントし、コード全体にわたって一貫して[インデントスタイル](https://en.wikipedia.org/wiki/Indent_style)を使用してください。そうすることで**読みやすく/管理しやすくなります**。 Stack Overflowに配置したコードでは、ユーザーが投稿を優先して投票する可能性が高くなり、人々はあなたの質問に答える時間がかかります。どのスタイルを選択するかは実際問題ではありません(一部の言語では、他のスタイルよりも適切なスタイルがいくつかあります)。しかし、*単一のプロジェクトのすべてのコードに対して、* 1つを選んで一貫して使用する*。 – Makyen