在struct中访问函数时的段错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在struct中访问函数时的段错误相关的知识,希望对你有一定的参考价值。

我试图在红黑树上实现集合。我的树是用以下结构定义的:

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中的结构中使用函数。我曾尝试在其他地方查找此问题,并且调试它几乎没有进展。当我尝试访问树结构中的compare函数时,为什么会出现段错误?

编辑:新集是以下函数的包装器,它创建一个新树。

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的指针的函数是在main函数中定义的。当我将它们移到主要功能之外时,它停止了segfaulting。

答案

你已经创建了一个struct,“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;

以上是关于在struct中访问函数时的段错误的主要内容,如果未能解决你的问题,请参考以下文章

GCC 生成的程序集 - C 函数调用时的段错误

未指定 lambda 函数的返回类型时的段错误

将结构从 main() 传递给工作函数时的段错误

使用 CUDA 流时的段错误

调用 glDrawElements 时的段错误

推送到成员向量时的段错误