gosseract icon indicating copy to clipboard operation
gosseract copied to clipboard

add a finalizer to close the client

Open yin1999 opened this issue 2 years ago • 0 comments

If the developer forgets to call the close method after creating the client, it will cause a memory leak.

To avoid this, I refer to the method in os.File. By adding a finalizer, the Close method will be called when the client is unreachable and the developer haven't call the Close method neither.

Test

client.go

// NewClient construct new Client. It's due to caller to Close this client.
func NewClient() *Client {
	client := &Client{
		api:        C.Create(),
		Variables:  map[SettableVariable]string{},
		Trim:       true,
		shouldInit: true,
		Languages:  []string{"eng"},
	}
	// set a finalizer to close the client when it's unused and not closed by the user
	runtime.SetFinalizer(client, (*Client).Close)
	return client
}

// Close frees allocated API. This MUST be called for ANY client constructed by "NewClient" function.
func (client *Client) Close() (err error) {
	// defer func() {
	// 	if e := recover(); e != nil {
	// 		err = fmt.Errorf("%v", e)
	// 	}
	// }()
	fmt.Println("Closed")
	C.Clear(client.api)
	C.Free(client.api)
	if client.pixImage != nil {
		C.DestroyPixImage(client.pixImage)
		client.pixImage = nil
	}
	// no need for a finalizer anymore
	runtime.SetFinalizer(client, nil)
	return err
}

test code

func main() {
	runGgosseract()
	runtime.GC() // run a garbage collection
	time.Sleep(2 * time.Second)
	// see "Close" before "exit"
	fmt.Println("exit")
}

func runGgosseract() {
	client := gosseract.NewClient()
	client.SetImage("path/to/image.png")
	text, _ := client.Text()
	fmt.Println(text)
}

yin1999 avatar Apr 10 '22 01:04 yin1999