Ошибка «освобождение указателя не было выделено» при использовании общей библиотеки go в python

# #python-3.x #go #cgo

Вопрос:

Я продолжаю получать эту ошибку всякий раз, когда запускаю общую библиотеку в pycharm:

 Python(20566,0x116d67dc0) malloc: *** error for object 0x5b6222f0: pointer being freed was not allocated
Python(20566,0x116d67dc0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
 

Вот мой код go, превращенный в общую библиотеку:

 package main

// #include <stdio.h>
// #include <stdlib.h>
// #include <errno.h>
import "C"


//export FreeCString
func FreeCString(ptr *C.char) {
    C.free(unsafe.Pointer(ptr))
}

//export TestString
func TestString() *C.char {
    return C.CString("Hello World")
}
 

Вот мой py-код:

 from ctypes import *
from ctypes import cdll

lib = cdll.LoadLibrary('./test.so')

b = lib.TestString()
lib.FreeCString(b)
print(b)
 

Что здесь происходит?

Ответ №1:

Во-первых, вы звоните print(b) после того, как освободили его, что явно плохая идея.

Возможно, что более важно, вы никогда не говорили Python о lib.TestString типе возврата, поэтому Python будет делать предположения. В частности:

 b = lib.TestString()
 

Поскольку вы никогда не устанавливаете lib.TestString.restype , Python считает, что возвращаемый тип является простым int . So b имеет значение 32-разрядный int , что является результатом отбрасывания 32 из 64 бит 64-разрядного c_void_p . (Чтобы исправить это, установите значение restype c_void_p . Вы argtypes также должны установить значение для всех вызываемых функций, хотя на машине, которую вы, вероятно, используете, это, вероятно, не будет иметь значения.)

 lib.FreeCString(b)
 

Это затем вызывает, косвенно, free((void *)(int)malloc(some_size)) . Поскольку значение указателя было повреждено в результате прохождения int , free вызов завершается неудачно, и программа останавливается до того, как вы перейдете к неправильному использованию-после-освобождения значения, в котором оно должно было храниться b .