You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言函数内存访问异常:BST指针传参后触发段错误

内存访问异常排查:BST搜索指针传入函数后触发段错误

在C语言开发中遇到内存访问异常:调用BST的search函数获取两个stazione类型指针后,用printf能正常输出其distanza字段,但将这两个指针传入pianificaPercorso函数后,访问指针字段会触发段错误。即使在pianificaPercorso内部重新执行搜索,问题依然存在。


调用代码片段

napoli = scanf("%d", &distanza);
int distanza2 = -1;
napoli = scanf("%d", &distanza2);
if(distanza == distanza2){
    printf("%d\n", distanza);
    return;
}
int flag = 1;
stazione *station1 = search(distanza, station->root, &flag);
stazione *station2 = search(distanza2, station->root, &flag);
printf("Stazioni %d e %d in arrivo\n", station1->distanza, station2->distanza);
pianificaPercorso(station1, station2);
return;

pianificaPercorso函数代码

void pianificaPercorso(stazione *station1, stazione *station2){
    printf("Pianificando stazioni %d e %d", station1->distanza, station2->distanza); 
    pila *p = NULL;
    stazione *progress = station2; //marks which stations have to be added to the route
    stazione *checking = NULL; //checks which stations are reachable
    int flag = 0; //once we've checked station 1, this becomes 1 and we can add a stop
    int gtfo = 1;
    if(station2->distanza < station1->distanza){
        checking = successore(station2);
        while(progress != station1){ //continue until we reach station 1
            while(flag == 0 && checking != NULL){
                if(checking == station1){
                    flag = 1;
                }
                if(reachable(checking, progress)){
                    progress = checking;
                    gtfo = 1;
                }
                checking = successore(checking);
            }
            if(gtfo == 0){ //if progress wasn't modified, we must exit
                printf("nessun percorso\n");
                return;
            }
            push(p, progress->distanza);
            checking = successore(progress);
            flag = 0;
            gtfo = 0;
        } //after this, the whole route will be pushed into the stack

    } else {
        checking = predecessore(station2);
        while(progress != station1){ //continue until we reach station 1
            while(flag == 0){
                if(checking == station1){
                    flag = 1;
                }
                if(reachable(checking, progress)){
                    progress = checking;
                    gtfo = 1;
                }
                checking = predecessore(checking);
            }
            if(gtfo == 0){ //if progress wasn't modified, we must exit
                printf("nessun percorso\n");
                return;
            }
            push(p, progress->distanza);
            checking = predecessore(progress);
            flag = 0;
            gtfo = 0;
        }
    }
    while(empty(p)){
        printf("%d ", pop(p));
    }
    printf("%d\n", station2->distanza);
    return;
}

结构体与search函数代码

typedef struct car{
    int autonomia;
    struct car *left;
    struct car *right;
    struct car *p;
}car;

typedef struct carTree{
    int nodi;
    car *root;
}carTree;

typedef struct stazione{
    int distanza;
    carTree cars;
    struct stazione *left;
    struct stazione *right;
    struct stazione *p;

}stazione;

typedef struct tree{
    int nodi;
    stazione *root;
}tree;

typedef struct pila{
    int value;
    struct pila *top;
    struct pila *next;
}pila;


stazione *search(int x, stazione *t, int *flag){
    if(t == NULL){
        *flag = 0;
        return NULL;
    }
    if(t->distanza == x){
        return t; //sta prendendo null per qualche motivo
    }
    else if(t->distanza < x){
        return search(x, t->right, flag);
    }
    else {
        return search(x, t->left, flag);
    }    
}

问题排查与修复方案

  1. 添加指针有效性检查
    search函数可能返回NULL(当目标值不存在于BST时),调用处未做判断。虽然外部printf偶然没崩溃,但传入函数后访问NULL指针的字段必然触发段错误。添加判断:

    int flag = 1;
    stazione *station1 = search(distanza, station->root, &flag);
    stazione *station2 = search(distanza2, station->root, &flag);
    if (station1 == NULL || station2 == NULL) {
        printf("Stazione non trovata\n");
        return;
    }
    
  2. 修复栈初始化逻辑
    pila *p = NULL;后直接调用push,若push未处理空指针,会导致非法访问。提前初始化栈节点:

    pila *p = malloc(sizeof(pila));
    p->top = NULL;
    

    同时确保push/pop函数能正确处理空栈边界。

  3. 完善successore/predecessore的空指针判断
    未给出实现的successore/predecessore可能返回NULL,在循环中需添加非空判断,避免连续调用导致的非法访问:

    // else分支内层循环修改为
    while(flag == 0 && checking != NULL){
    
  4. 修正empty函数的循环条件
    输出栈的循环while(empty(p))逻辑错误,若empty在栈非空时返回0,循环永远不会执行。改为:

    while(!empty(p)){
        printf("%d ", pop(p));
    }
    

    同时确认empty函数逻辑正确:

    int empty(pila *p) {
        return p->top == NULL;
    }
    

内容的提问来源于stack exchange,提问作者Andrea Colombo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:11:00