ObjectBox一对多关联在ARMv7 Linux设备触发panic求助
问题分析与解决方案
问题概述
代码未使用一对多关联时,可在x86 Windows和ARMv7 Linux设备正常运行;添加Task与Workers的一对多关联后,x86 Windows仍正常,但ARMv7 Linux设备执行box.Get(id)时触发空指针panic。
环境信息
- ObjectBox Go版本:objectbox-go v1.8.0
- ObjectBox核心库版本:libobjectbox.so v4.0.1
- 运行设备:x86 Windows、ARMv7 Linux
- 复现概率:100%
代码示例
main.go
package main import ( "fmt" "github.com/objectbox/objectbox-go/objectbox" "objectboxTest/objectboxlib/model" ) func initObjectBox() *objectbox.ObjectBox { objectBox, err := objectbox.NewBuilder().Model(model.ObjectBoxModel()).Directory("./opt").Build() if err != nil { fmt.Println(err) return nil } return objectBox } func main() { // 初始化ObjectBox ob := initObjectBox() defer ob.Close() // 服务端应用中只需保留实例, shutdown时关闭即可 box := model.BoxForTask(ob) box2 := model.BoxForWorkers(ob) if box == nil || box2 == nil { panic("box初始化失败") } worker1 := model.Workers{Name: "Petter", Age: 18} worker2 := model.Workers{Name: "Leven", Age: 28} workers := []*model.Workers{&worker1, &worker2} id, _ := box.Put(&model.Task{ Text: "Buy milk", Workers: workers, }) tasks, err := box.Get(id) // 此处触发panic....... if err != nil { fmt.Println("读取错误 ", err) return } fmt.Println(tasks) }
model/task.go
package model //go:generate go run github.com/objectbox/objectbox-go/cmd/objectbox-gogen // 新增一行启用同步: // `objectbox:"sync"` type Task struct { Id uint64 Text string Name string DataType string Value float64 ValueStr string DateCreated int64 DateFinished int64 Workers []*Workers // 一对多关联字段 } type Workers struct { Id uint64 Name string Age int }
运行日志
Windows平台日志
&{6 Buy milk 0 0 0 [0xc000086020 0xc000086040]}
ARMv7 Linux平台日志
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x13d6c8] goroutine 1 [running, locked to thread]: github.com/objectbox/objectbox-go/objectbox.dataVisitorDispatch(0xb55f17b0, 0x40, 0x4137c0) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/datavisitorc.go:43 +0x50 github.com/objectbox/objectbox-go/objectbox._Cfunc_obx_box_visit_many(0x2cdff0, 0x2ce078, 0x142d4c, 0x4137c0) _cgo_gotypes.go:745 +0x38 github.com/objectbox/objectbox-go/objectbox.(*Box).GetManyExisting.func2.1(0x5147b0, 0x5147e0, 0x4137c0) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:531 +0xc8 github.com/objectbox/objectbox-go/objectbox.(*Box).GetManyExisting.func2(0x4137c0) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:531 +0x70 github.com/objectbox/objectbox-go/objectbox.(*Box).readUsingVisitor.func2.1() /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:621 +0x24 github.com/objectbox/objectbox-go/objectbox.cCall(0x4d7cf4) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/c-tools.go:34 +0x20 github.com/objectbox/objectbox-go/objectbox.(*Box).readUsingVisitor.func2() /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:621 +0x4c github.com/objectbox/objectbox-go/objectbox.(*ObjectBox).runInTxn(0x505860, 0x1, 0x4d7d64) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/objectbox.go:155 +0xcc github.com/objectbox/objectbox-go/objectbox.(*ObjectBox).RunInReadTx(...) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/objectbox.go:110 github.com/objectbox/objectbox-go/objectbox.(*Box).readUsingVisitor(0x5147b0, 0x1, 0x4d7da0) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:620 +0x27c github.com/objectbox/objectbox-go/objectbox.(*Box).GetManyExisting(0x5147b0, {0x4137b0, 0x2, 0x2}) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:533 +0x158 objectboxTest/objectboxlib/model.(*WorkersBox).GetManyExisting(...) /mnt/d/gitlab/tools/objectboxTest/objectboxlib/model/task.obx.go:617 objectboxTest/objectboxlib/model.task_EntityInfo.Load({{0x1}, 0x284bb4920ec6bdbe}, 0x505860, {0xb55f1680, 0x80, 0x80}) /mnt/d/gitlab/tools/objectboxTest/objectboxlib/model/task.obx.go:170 +0x144 github.com/objectbox/objectbox-go/objectbox.(*Box).Get.func1() /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:479 +0x18c github.com/objectbox/objectbox-go/objectbox.(*ObjectBox).runInTxn(0x505860, 0x1, 0x4d7f10) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/objectbox.go:155 +0xcc github.com/objectbox/objectbox-go/objectbox.(*ObjectBox).RunInReadTx(...) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/objectbox.go:110 github.com/objectbox/objectbox-go/objectbox.(*Box).Get(0x514790, 0x3) /home/lich/go/pkg/mod/github.com/levin-go/objectbox-go@v0.0.0-20240826085105-f32fc4305353/objectbox/box.go:470 +0x80 objectboxTest/objectboxlib/model.(*TaskBox).Get(0x4d7f90, 0x3) /mnt/d/gitlab/tools/objectboxTest/objectboxlib/model/task.obx.go:258 +0x30 main.main() /mnt/d/gitlab/tools/objectboxTest/main.go:34 +0x198
解决方案
从panic栈信息来看,问题出在ARMv7平台下ObjectBox处理一对多关联的C层调用中,空指针访问导致段错误。可尝试以下方案:
升级ObjectBox版本
当前使用的版本并非最新,后续版本大概率修复了ARM架构下的关联处理bug:- 执行
go get github.com/objectbox/objectbox-go@latest更新Go绑定 - 下载对应ARMv7平台的最新libobjectbox.so替换现有文件
- 执行
显式定义关联关系
仅通过切片声明一对多未明确ObjectBox规则,可能导致代码生成工具在ARM平台生成的逻辑异常。修改Task结构体的关联字段,添加标签明确关联:type Task struct { // ... 其他字段 Workers []*Workers `objectbox:"link"` }修改后重新执行
go generate生成模型代码,再测试运行。手动处理关联数据
如果升级版本和显式标签无效,可临时绕过ObjectBox的自动关联加载:- 先存储所有Workers实例,获取它们的ID
- 在Task中添加
WorkerIds []uint64字段存储关联ID - 查询Task后,再通过ID批量查询Workers实例
修改后的模型示例:
type Task struct { Id uint64 Text string // ... 其他字段 WorkerIds []uint64 `objectbox:"long"` } type Workers struct { Id uint64 Name string Age int }对应的业务代码调整:
// 先存储Workers workerIds, _ := box2.PutMany(workers) // 存储Task,关联Worker ID id, _ := box.Put(&model.Task{ Text: "Buy milk", WorkerIds: workerIds, }) // 查询Task后手动加载Workers task, err := box.Get(id) if err != nil { fmt.Println("读取错误 ", err) return } workers, _ := box2.GetMany(task.WorkerIds) task.Workers = workers // 手动赋值关联数据 fmt.Println(task)
内容的提问来源于stack exchange,提问作者Huihui
相关产品推荐
相关产品推荐

