【发布时间】:2017-12-25 04:15:15
【问题描述】:
我正在尝试在红黑树上实现集合。我的树是用以下结构定义的:
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;
}
}
这是我用来测试并从中获取段错误的代码。请注意,我有
typedef struct rb_tree *set;
typedef struct rb_node *element;
在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);
}
此代码在第二次插入时失败,因为它调用了 tree->compare。使用 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 中运行良好。这是我第一次在 c 结构中使用函数。我试图在其他地方查找这个问题,但调试它几乎没有进展。当我尝试访问树结构中的比较函数时,为什么会出现段错误?
编辑: New set 是以下函数的包装器,用于创建新树。
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);
}
编辑 2: 我解决了我的问题。我将指针传递给 new_set 的函数是在主函数中定义的。当我将它们移到主要功能之外时,它停止了段错误。
【问题讨论】:
-
new_set显示。这也不是minimal reproducible example -
请,缩进您的代码并在整个代码中始终使用indenting style。这样做会使它更加更容易阅读/维护。对您放置在 Stack Overflow 上的代码执行此操作会使用户更有可能对您的帖子进行投票,并且人们会花时间回答您的问题。您选择哪种样式并不重要(尽管对于某些语言,某些样式比其他样式更合适)。但是,选择一个并一致地使用它用于单个项目中的所有代码。
标签: c pointers struct gdb function-pointers