使用g_slist_copy_deep拷贝GSList出现段错误相关问题求助
段错误根因
- 对
GCopyFunc的签名和参数含义理解错误
GLib规定GCopyFunc的正确签名为gpointer (*GCopyFunc) (gconstpointer src, gpointer user_data):
- 第一个参数
src是当前正在拷贝的原链表节点存储的数据指针,也就是你存入节点的Account*,不是GSList节点本身,更不是全局链表头。你将该指针强转为GSList*后访问->data属于非法内存访问,是段错误的直接原因。 - 返回值是你拷贝生成的新数据指针,返回后
g_slist_copy_deep会自动将其作为新链表对应节点的data,不需要手动添加到临时链表。
- 拷贝函数返回值类型错误
你的代码将返回值写为GCopyFunc类型,和要求的gpointer完全不符,属于函数签名不匹配。 - 局部变量生命周期错误
你定义的temporary_account是栈上局部变量,函数返回后内存会被回收,即使逻辑正确返回该地址也会造成野指针。
修正代码
正确的拷贝函数
gpointer account_copy(gconstpointer src, gpointer user_data) { // 直接强转为原数据类型Account*即可 const Account* src_acc = (const Account*)src; // 堆内存分配新的Account对象,生命周期不受函数退出影响 Account* new_acc = g_new(Account, 1); // 拷贝字段 strcpy(new_acc->number, src_acc->number); strcpy(new_acc->description, src_acc->description); // 返回新对象指针,g_slist_copy_deep会自动处理节点添加逻辑 return new_acc; }
调用示例
GSList *master_account_list = read_account_numbers(); // 直接传入正确的拷贝函数即可,不需要强制类型转换 GSList *temporary_account_list = g_slist_copy_deep(master_account_list, account_copy, NULL);
注意事项
- 临时链表使用完毕后需要用
g_slist_free_full释放,避免内存泄漏:
// 第二个参数是每个节点data的释放函数,这里直接用g_free即可 g_slist_free_full(temporary_account_list, g_free);
- 拷贝过程不需要手动遍历原链表、手动添加节点到新链表,这些逻辑
g_slist_copy_deep内部已经全部实现。
内容的提问来源于stack exchange,提问作者9-Pin
相关产品推荐
相关产品推荐

