Home  >  Article  >  Backend Development  >  Go: How to handle memory leaks when returning a CString?

Go: How to handle memory leaks when returning a CString?

王林
王林forward
2024-02-13 10:00:10983browse

Go:返回 CString 时如何处理内存泄漏?

php editor Xigua is here to share with you the solution to the memory leak problem when returning CString in the Go language. In Go, C strings are null-terminated byte arrays, while Go strings are length-prefixed byte arrays. When we need to convert a Go string to a C string and back, we need to pay attention to the allocation and release of memory to avoid memory leaks. This article will introduce several methods to deal with memory leaks to help you solve this common problem.

Question content

I have the following function signature, which then returns a json string

func getdata(symbol, day, month, year *c.char) *c.char {
  combine, _ := json.marshal(combinerecords)
  log.println(string(combine))
  return c.cstring(string(combine))
}

Then call the go code in python

import ctypes
from time import sleep
library = ctypes.cdll.LoadLibrary('./deribit.so')
get_data = library.getData

# Make python convert its values to C representation.
# get_data.argtypes = [ctypes.c_char_p, ctypes.c_char_p,ctypes.c_char_p,ctypes.c_char_p]
get_data.restype = ctypes.c_char_p

for i in range(1,100):
    j= get_data("BTC".encode("utf-8"), "5".encode("utf-8"), "JAN".encode("utf-8"), "23".encode("utf-8"))
    # j= get_data(b"BTC", b"3", b"JAN", b"23")
    print('prnting in Python')
    # print(j)
    sleep(1)

It works fine on the python side, but I'm worried about a memory leak when calling the function in a loop on the python side.

How to deal with memory leaks? Should I return bytes instead of cstring and handle the bytes on the python side to avoid memory leaks? I did find this link to handle it but somehow I don't know the size of the json string returned after marshalling

Workaround

python should look like this:

import ctypes
from time import sleep
library = ctypes.cdll('./stackoverflow.so')
get_data = library.getdata
free_me = library.freeme
free_me.argtypes = [ctypes.pointer(ctypes.c_char)]
get_data.restype = ctypes.pointer(ctypes.c_char)

for i in range(1,100):
  j = get_data("", "", "")
  print(ctypes.c_char_p.from_buffer(j).value)
  free_me(j)
  sleep(1)

go should look like this:

package main
/*
#include <stdlib.h>
*/
import "c"
import (
  "log"
  "unsafe"
)

//export getdata
func getdata(symbol, day, month, year *c.char) *c.char {
  combine := "combine"
  log.println(string(combine))
  return c.cstring(string(combine))
}

//export freeme
func freeme(data *c.char) {
  c.free(unsafe.pointer(data))
}

func main() {}

And use this command line to generate the shared library:

python3 --version
python 3.8.10 
go version
go version go1.19.2 linux/amd64
go build -o stackoverflow.so -buildmode=c-shared github.com/sjeandeaux/stackoverflow
python3 stackoverflow.py 
2023/01/03 13:54:14 combine
b'combine'                                                                                                                                  
...
from ubuntu:18.04

run apt-get update -y && apt-get install python -y

copy stackoverflow.so stackoverflow.so
copy stackoverflow.py stackoverflow.py

cmd ["python", "stackoverflow.py"]
docker build --tag stackoverflow .
docker run -ti stackoverflow
2023/01/03 15:04:24 combine
b'combine'
...

The above is the detailed content of Go: How to handle memory leaks when returning a CString?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete