为何在main函数中可为指针赋值NULL,其他函数中却触发段错误?
问题本质与解决办法
你两段代码其实都有严重问题——cache是未初始化的野指针,直接访问cache->next属于非法操作内存,触发段错误只是系统刚好检测到了非法访问,main函数里没报错纯粹是运气好,并不是代码正确。
为什么会这样?
当你声明struct list_node *cache;时,这个指针变量里存储的是随机的内存地址,可能指向系统保护的内存区域,也可能指向某个可写但不属于你的内存块:
- 在
new_list函数里,这个随机地址刚好落在了系统不允许写入的区域,所以触发段错误。 - 在main函数里,随机地址可能刚好指向了栈上某个可写的位置,所以没立刻报错,但这依然是未定义行为,后续操作随时可能崩溃或出现奇怪的问题。
正确的链表节点初始化方式
要创建链表节点,必须先给指针分配有效的内存空间,用malloc从堆上分配是常见做法:
#include <stdlib.h> struct list_node { unsigned long value; struct list_node *next; }; // 创建并初始化一个新节点,返回节点指针 struct list_node* new_list() { // 分配内存,大小为结构体的字节数 struct list_node *cache = malloc(sizeof(struct list_node)); // 必须检查内存分配是否成功,防止malloc返回NULL if (cache != NULL) { cache->next = NULL; // 现在操作的是合法内存 cache->value = 0; // 顺便初始化value字段 } return cache; } int main() { struct list_node *head = new_list(); // 这里可以添加节点、遍历链表等操作... // 记得用完后释放内存,避免内存泄漏 free(head); return 0; }
如果想在函数里修改外部的头指针,也可以用指针的指针:
void new_list(struct list_node **head) { *head = malloc(sizeof(struct list_node)); if (*head != NULL) { (*head)->next = NULL; (*head)->value = 0; } } int main() { struct list_node *head = NULL; new_list(&head); // 使用链表... free(head); return 0; }
总结
永远不要操作未初始化的指针,使用指针前必须确保它指向合法的内存空间——要么是堆上分配的内存(malloc/calloc),要么是栈上已存在的变量地址。
内容的提问来源于stack exchange,提问作者GandalfGreybeard
相关产品推荐
相关产品推荐

