Skip to content

🐛 fix(jieba): 修复内存释放问题#131

Merged
yanyiwu merged 2 commits intoyanyiwu:masterfrom
kevinmatthe:bugfix/fix_double_free
Jun 4, 2025
Merged

🐛 fix(jieba): 修复内存释放问题#131
yanyiwu merged 2 commits intoyanyiwu:masterfrom
kevinmatthe:bugfix/fix_double_free

Conversation

@kevinmatthe
Copy link
Copy Markdown
Contributor

  • 添加原子操作确保只释放一次内存
  • 优化导入包顺序
  • 添加freed标志位防止重复释放

- 添加原子操作确保只释放一次内存
- 优化导入包顺序
- 添加freed标志位防止重复释放
- 新增TestTypicalDoubleFree测试函数
- 使用runtime.GC()调用垃圾回收器以运行finalizers
- 确保jieba实例正确释放
@kevinmatthe
Copy link
Copy Markdown
Contributor Author

kevinmatthe commented Jun 4, 2025

经过充分的调查可以明确,Double Free的问题来源于下面的情况:

此处的Finalizer将会为GC注册Jieba Object的回收函数

gojieba/jieba.go

Lines 58 to 59 in 51c61c7

// set finalizer to free the memory when the object is garbage collected
runtime.SetFinalizer(jieba, (*Jieba).Free)

而在Free的实现中,没有校验CGO对象是否已经被释放过:

gojieba/jieba.go

Lines 63 to 65 in 51c61c7

func (x *Jieba) Free() {
C.FreeJieba(x.jieba)
}

所以,在典型的使用场景下:

	jieba := gojieba.NewJieba()
	defer jieba.Free()

在函数退出时,CGO 对象的释放操作会被defer执行。然而,Go 的垃圾回收器(GC)具有非确定性的触发时机。当 GC 在对象已被手动释放之后再次尝试回收该对象时,CGO 层会调用底层 C++ 逻辑对已释放的内存执行重复的 delete 操作,进而访问无效内存地址,导致段错误(segmentation fault),最终引发程序以 Fatal 异常方式崩溃。

SIGSEGV: segmentation violation
PC=0x7fb5d499ee3a m=7 sigcode=1 addr=0x7fb500005c79
signal arrived during cgo execution

可以通过手动触发运行时的GC,来复现这一典型问题:

	x := NewJieba()
	defer x.Free()

	runtime.GC() // call GC to run finalizers

上面的代码可以稳定的触发段错误异常,导致程序退出。修复前导致的退出现场,可见测试PR:#132

同时该项测试也提交到了当前PR中,用于验证改动修复的有效性。

@kevinmatthe
Copy link
Copy Markdown
Contributor Author

关联Issue #87 #125 #128 #112 #122

@kevinmatthe
Copy link
Copy Markdown
Contributor Author

kevinmatthe commented Jun 4, 2025

@yanyiwu Please review this

@yanyiwu yanyiwu merged commit 6df97d2 into yanyiwu:master Jun 4, 2025
24 checks passed
@kevinmatthe
Copy link
Copy Markdown
Contributor Author

Maybe create a release for the changes since 2024?

@yanyiwu
Copy link
Copy Markdown
Owner

yanyiwu commented Jun 6, 2025

https://github.com/yanyiwu/gojieba/releases/tag/v1.4.6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants