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); } }
问题排查与修复方案
添加指针有效性检查
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; }修复栈初始化逻辑
pila *p = NULL;后直接调用push,若push未处理空指针,会导致非法访问。提前初始化栈节点:pila *p = malloc(sizeof(pila)); p->top = NULL;同时确保
push/pop函数能正确处理空栈边界。完善successore/predecessore的空指针判断
未给出实现的successore/predecessore可能返回NULL,在循环中需添加非空判断,避免连续调用导致的非法访问:// else分支内层循环修改为 while(flag == 0 && checking != NULL){修正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
相关产品推荐
相关产品推荐

