在golang中,尝试使用arena进行手动内存释放
代码:
package main
import (
"arena"
"encoding/json"
"fmt"
"runtime"
"strconv"
"strings"
"github.com/glebarez/sqlite"
"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
)
type RoadDeviceVehicle struct {
RoadPoint string
}
type TT struct {
PointX string `json:"pointX"`
PointY string `json:"pointY"`
Timestamp string `json:"timestamp"`
}
type TTT struct {
PointX float32
PointY float32
Timestamp int64
}
func main() {
db, err := gorm.Open(sqlite.Open("road_device_vehicle.db"), &gorm.Config{})
if err != nil {
fmt.Println(err)
panic("failed to connect database")
}
tmem := arena.NewArena()
roadVehicles := arena.MakeSlice[RoadDeviceVehicle](tmem, 0, 1500000)
db.Table("road_device_vehicle").Select("road_point").Find(&roadVehicles)
tts := arena.MakeSlice[[]TT](tmem, len(roadVehicles), len(roadVehicles))
for idx := range roadVehicles {
tts[idx] = make([]TT, 0, 20)
s := strings.Replace(roadVehicles[idx].RoadPoint, "\\", "", -1)
json.Unmarshal([]byte(s), &tts[idx])
}
tttsmem := arena.NewArena()
ttts := arena.MakeSlice[[]TTT](tttsmem, len(tts), len(tts))
for idx := range tts {
ttts[idx] = arena.MakeSlice[TTT](tttsmem, len(tts[idx]), len(tts[idx]))
for idx2 := range tts[idx] {
t, err := strconv.ParseFloat(tts[idx][idx2].PointX, 32)
if err != nil {
fmt.Println(err)
return
}
ttts[idx][idx2].PointX = float32(t)
t, err = strconv.ParseFloat(tts[idx][idx2].PointY, 32)
if err != nil {
fmt.Println(err)
return
}
ttts[idx][idx2].PointY = float32(t)
ttts[idx][idx2].Timestamp, err = strconv.ParseInt(tts[idx][idx2].Timestamp, 10, 64)
if err != nil {
fmt.Println(err)
return
}
}
}
tmem.Free()
runtime.GC()
app := fiber.New()
app.Get("/db", func(c *fiber.Ctx) error {
fmt.Println(ttts[0][0])
return c.SendString("Hello, World!")
})
app.Listen(":3000")
}
在以上代码中,RoadPoint字符串类似于如下:
[{\"pointX\":\"212.13\",\"pointY\":\"61724922.54\",\"timestamp\":\"1704970150739\"},{\"pointX\":\"228.30\",\"pointY\":\"61728661.51\",\"timestamp\":\"1704970152777\"},{\"pointX\":\"188.10\",\"pointY\":\"61732802.98\",\"timestamp\":\"1704970154739\"},{\"pointX\":\"188.04\",\"pointY\":\"61737013.77\",\"timestamp\":\"1704970156738\"},{\"pointX\":\"151.57\",\"pointY\":\"61742215.45\",\"timestamp\":\"1704970158777\"}]
使用tmem.Free()之后,读取ttts
字段会报错,信息如下:
accessed data from freed user arena 0x40c0007eff70
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0x40c0007eff70 pc=0xfdf390]
请问为什么会出现这种情况,ttts不是使用tttsmem分配的吗,为什么我free了tmem后会导致ttts无法读取
使用普通的make,则可以依靠垃圾回收正确获取结果