195、从 Bug 到经验沉淀:如何把一次排错变成团队的永久知识资产
2026/7/11 0:02:04
typedef struct dnode { DataType_t data; struct dnode* ppre; struct dnode* pnext; }Dnode_t;双向链表在单向链表的基础上多一个头指针指向前一个节点的地址
//双向链表对象类型 typedef struct dlink { Dnode_t* phead; int clen; }Dlink_t;Dlink_t* create_doulink() { Dlink_t* pdlink = malloc(sizeof(Dlink_t)); if (NULL == pdlink) { printf("malloc error\n"); return NULL; } pdlink->phead = NULL; pdlink->clen = 0; return pdlink; }Dnode_t* create_node(DataType_t data) { Dnode_t* pnode = malloc(sizeof(Dnode_t)); if (NULL == pnode) { printf("malloc error"); return NULL; } pnode->data = data; pnode->pnext = NULL; pnode->ppre = NULL; return pnode; }int is_empty_dlink(Dlink_t* pdlink) { if (NULL == pdlink->phead) { return 1; } return 0; }int insert_doulink_head(Dlink_t* pdlink, DataType_t data) { Dnode_t* pnode = create_node(data); if (NULL == pnode) { return -1; } if (is_empty_dlink(pdlink)) { pdlink->phead = pnode; } else { pnode->pnext = pdlink->phead; pdlink->phead->ppre = pnode; pdlink->phead = pnode; } pdlink->clen++; return 0; }int insert_doulink_tail(Dlink_t* pdlink, DataType_t data) { Dnode_t* pnode = create_node(data); Dnode_t* ptmp = pdlink->phead; if (NULL == pnode) { return -1; } if (is_empty_dlink(pdlink)) { pdlink->phead = pnode; } else { while (ptmp->pnext != NULL) { ptmp = ptmp->pnext; } ptmp->pnext = pnode; pnode->ppre = ptmp; } pdlink->clen++; return 0; }int delete_doulink_head(Dlink_t* pdlink) { if (is_empty_dlink(pdlink)) { return -1; } Dnode_t* ptmp = pdlink->phead; pdlink->phead = ptmp->pnext; if (ptmp->pnext != NULL) { ptmp->pnext->ppre = NULL; } free(ptmp); pdlink->clen--; return 0; }int delete_doulink_tail(Dlink_t* pdlink) { Dnode_t* ptmp = pdlink->phead; if (NULL == ptmp) { return -1; } if (is_empty_dlink(pdlink)) { return -1; } while (ptmp->pnext != NULL) { ptmp = ptmp->pnext; } if (ptmp->ppre != NULL) { ptmp->ppre->pnext = NULL; } else { pdlink->phead = NULL; } free(ptmp); pdlink->clen--; return 0; }void show_doulink(Dlink_t* pdlink, int dir) { if (is_empty_dlink(pdlink)) { return; } Dnode_t* ptmp = pdlink->phead; if (dir) { while (ptmp) { printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score); ptmp = ptmp->pnext; } } else { while (ptmp->pnext) { ptmp = ptmp->pnext; } while (ptmp) { printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score); ptmp = ptmp->ppre; } } printf("\n"); }此处示例是用名字查找
Dnode_t* find_doulink_node(Dlink_t* pdlink, char* name) { if (is_empty_dlink(pdlink)) { return NULL; } Dnode_t* ptmp = pdlink->phead; while (ptmp != NULL) { if (0 == strcmp(ptmp->data.name, name)) { return ptmp; } ptmp = ptmp->pnext; } return NULL; }int change_doulink_score(Dlink_t* pdlink, char* name, int score) { Dnode_t* ptmp = NULL; ptmp = find_doulink_node(pdlink, name); if (ptmp != NULL) { ptmp->data.score = score; return 0; } return -1; }int delete_doulink_node(Dlink_t* pdlink, char* name) { if (is_empty_dlink(pdlink)) { return -1; } Dnode_t* ptmp = NULL; ptmp = find_doulink_node(pdlink, name); if (NULL == ptmp) { return -1; } if (NULL == ptmp->ppre) { delete_doulink_head(pdlink); } else if (NULL == ptmp->pnext) { delete_doulink_tail(pdlink); } else { ptmp->ppre->pnext = ptmp->pnext; ptmp->pnext->ppre = ptmp->ppre; pdlink->clen--; } free(ptmp); return 0; }void destroy_doulink(Dlink_t* pdlink) { while (!is_empty_dlink(pdlink)) { delete_doulink_head(pdlink); } free(pdlink); }Linux内核中所使用到的一种链表结构,使用同一种结构可以存储不同类型的链表
普通链表:链表结点中包含数据
内核链表:数据中包含链表结点
创建:创建空白结点
插入:申请结点,并按照循环链表插入(插入的链表结点首地址即数据结点首地址)
访问结点:通过遍历找到每个结点的首地址,强制类型转换获得对应数据空间首地址