好的,所以我几周只做C,我遇到了一些问题。我有一个充满Bsig
指针的优先级队列。作为一项附加功能,我希望每当弹出Bsig
时,我们都会执行自定义函数。
typedef struct bsig{
// some more fields here, but they're not important
struct onpop_t *on_pop;
} Bsig;
typedef struct onpop_t {
struct onpop_t *next;
int (*do_on_pop)(Bsig *caller);
} Onpop;
int pop(SigPQ *q, Bsig* ret_sig){
if (q->size < 1){
return 0;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
ret_sig = signal;
return 1;
}
基本上,只要我们调用pop,就应该启动do_on_pop函数。此外,pop接收一个信号指针,该指针被从队列中弹出的任何内容覆盖。所有这些都发生在main.c包含的两个文件中。以下是来自main(其中testpop
是一个自定义函数,juts随机打印 - 它在main.c文件中声明和定义):
Bsig *sig1 = new_signal(1000, 0);
Onpop *onpop1 = malloc(sizeof(Onpop));
onpop1->do_on_pop = &testpop;
sig1->on_pop = onpop1;
push(pq, sig1);
Bsig *ret_sig;
pop(pq,ret_sig);
到目前为止一切都很好 - 自定义函数testpop
被调用。但
ret_sig->on_pop->do_on_pop(ret_sig);
来自main的给出了分段错误!我不明白为什么。 ret_sig地址和信号地址应该相同,并且函数调用是相同的 - 唯一的区别是一个从main调用,一个从包含的.c文件调用。任何人都可以发光吗?
答案 0 :(得分:2)
您需要通过引用明确传递ret_sig
。
int pop(SigPQ *q, Bsig** ret_sig){
if (q->size < 1){
return 0;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
*ret_sig = signal;
return 1;
}
并传递ret_sig
Bsig *ret_sig;
pop(pq,&ret_sig);
或者更改函数以返回指针而不是int
(更干净):
Bsig *pop(SigPQ *q){
if (q->size < 1){
return NULL;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
return signal;
}
并指定返回值:
Bsig *ret_sig = pop(pq);