英文:
Finding Memory Leak in Go Application
问题
我有一个简单的程序,它从网络摄像头读取帧,并将它们的指针放入一个goroutine中的通道中。另一部分从通道中读取帧指针,并将它们弹出到另一个队列中。这个队列对它们进行一些额外的处理,当这个额外的处理完成时,会分配一些内存,但显然这些内存从未被垃圾回收。我在试图弄清楚原因时陷入困境:
这个函数在循环中从通道中读取帧:
func (mr *OpenCVMotionRunner) Run() error {
log.Println("Starting motion detection... ")
win := opencv.NewWindow("GoOpenCV: VideoPlayer")
defer win.Destroy()
test := mr.md.(*CV2FrameDiffMotionDetector)
for {
f := mr.imageChan.PopFrame()
mr.frame = nil
switch f := f.(type) {
default:
return fmt.Errorf("Unknown frame type")
case *BSFrame:
mr.frame = f.ToOpenCVFrame()
case *OpenCVFrame:
mr.frame = f
}
f = nil
test.SetCurrent(mr.frame)
delta := test.Delta()
if delta != nil {
win.ShowImage(delta)
opencv.WaitKey(1)
} else {
fmt.Println("wtf")
}
}
return nil
}
问题似乎出在这里:
mr.frame = f.ToOpenCVFrame()
这是类型和方法的定义:
// Frame with byte slice image
type BSFrame struct {
image []byte
Time time.Time
Width uint32
Height uint32
}
func (f *BSFrame) ToOpenCVFrame() *OpenCVFrame {
img := opencv.DecodeImageMem(f.image)
return &OpenCVFrame{
image: img,
Time: f.Time,
Width: f.Width,
Height: f.Height,
}
}
这是目标类型的定义:
type OpenCVFrame struct {
image *opencv.IplImage
Time time.Time
Width uint32
Height uint32
}
顺便提一下,PopFrame只是一个别名为通道的类型上的方法:
type BSFrameChan chan *BSFrame
func (fc BSFrameChan) PopFrame() (frame Frame) {
frame = <-fc
return
}
希望这些代码足够展示问题。如果需要的话,其余代码可以在这里找到。
英文:
I've got a simple program that reads frames off a webcam and puts pointers to them on a channel in a goroutine. Another portion reads the frame pointers from the channel and pops them onto another queue. This other queue then does some additional processing to them, and when this additional processing is done, a bunch of memory gets allocated that apparently never gets garbage collected. I'm in over my head trying to figure out why:
This function reads the frames off the channel in a loop:
func (mr *OpenCVMotionRunner) Run() error {
log.Println("Starting motion detection... ")
// inMotion := false
win := opencv.NewWindow("GoOpenCV: VideoPlayer")
defer win.Destroy()
test := mr.md.(*CV2FrameDiffMotionDetector)
for {
f := mr.imageChan.PopFrame()
mr.frame = nil
switch f := f.(type) {
default:
return fmt.Errorf("Unknown frame type")
case *BSFrame:
mr.frame = f.ToOpenCVFrame()
case *OpenCVFrame:
mr.frame = f
}
f = nil
test.SetCurrent(mr.frame)
delta := test.Delta()
// win.ShowImage(mr.frame.image)
if delta != nil {
win.ShowImage(delta)
opencv.WaitKey(1)
} else {
fmt.Println("wtf")
}
}
return nil
}
It appears that the problematic part is this specifically:
mr.frame = f.ToOpenCVFrame()
This is the type and the method:
// Frame with byte slice image
type BSFrame struct {
image []byte
Time time.Time
Width uint32
Height uint32
}
func (f *BSFrame) ToOpenCVFrame() *OpenCVFrame {
img := opencv.DecodeImageMem(f.image)
return &OpenCVFrame{
image: img,
Time: f.Time,
Width: f.Width,
Height: f.Height,
}
}
This is the destination type:
type OpenCVFrame struct {
image *opencv.IplImage
Time time.Time
Width uint32
Height uint32
}
PopFrame, FYI, is just a method on an type that aliases a channel:
type BSFrameChan chan *BSFrame
func (fc BSFrameChan) PopFrame() (frame Frame) {
frame = <-fc
return
}
Hopefully this is enough code for the problem to present itself. The rest is here if needed.
答案1
得分: 0
我正在使用的go-opencv库提供了一个Release
方法,用于在使用完图像后释放内存。这可以解决这个问题。
英文:
The go library I'm using for the OpenCV bindings provides a Release
method on images to deallocate memory when done with an image. This fixes the problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论