es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

pybind11: método de clase de C++ devuelve un puntero que falló en tiempo de ejecución

Intenté un ejemplo simple de pybind11, como este:

“`c++
// cabecera
class Test
{
private:
int* m_a;
public:
Test(int a);
~Test();
int* getA();
};


```c++ // cpp Test::Test(int a){ m_a = new int(a); } Test::~Test(){ delete m_a; } int* Test::getA(){ return m_a; }

“`c++
// enlace
namespace py = pybind11;

PYBIND11_MODULE(bindtestlib, m)
{
py::class_<test>(m, "Test")
.def(py::init<int>())
// como dice la guía oficial, usa la política de referencia si devuelve un puntero desnudo
.def("getA", &Test::getA, py::return_value_policy::reference);
}

<pre><code><br />luego importa este módulo en el script de python

“`python
import bindtestlib as bt

t = bt.Test(2)
a = t.getA()
print(a)

ejecutar este script imprimirá el valor de a correctamente, pero encontrará un error antes de salir

imagen

luego se queda atascado sin salir

He intentado dos formas:
1. eliminar el delete m_a en el destructor, luego el script funciona bien, pero creo que esta no es una forma correcta, puede causar pérdida de memoria.
2. depurar pybind11, encontré que antes de que ocurra la excepción, se detiene en un lugar diferente.

Me tiene confundido. No puedo entender qué error he cometido.

Tags:  ,

Answer

  1. Avatar for davy.ai

    El error que se encuentra antes de salir del script es una falla de segmentación (SIGSEGV), lo cual indica que el programa está intentando acceder a una memoria a la cual no tiene permiso. Después de examinar el código que proporcionaste, parece que el problema está en la función getA() de la clase Test.

    La función getA() devuelve un puntero sin formato a la variable miembro m_a, la cual es asignada en el montón usando new en el constructor. Cuando el objeto Test es destruido, el destructor llama a delete en m_a para desasignar la memoria. Sin embargo, cuando la función getA() devuelve el puntero sin formato, no se garantiza que el objeto Test todavía esté vivo y que la memoria m_a sea válida.

    Para solucionar este problema, puedes cambiar la política de retorno return_value_policy a copy en lugar de reference. Esto creará una copia de la memoria de m_a antes de devolverla a Python, de modo que el objeto pueda ser eliminado de forma segura sin afectar al objeto Python.

    Aquí está el código de vinculación actualizado:

    “`c++
    namespace py = pybind11;

    PYBIND11_MODULE(bindtestlib, m)
    {
    py::class_(m, “Test”)
    .def(py::init())
    .def(“getA”, &Test::getA, py::return_value_policy::copy);
    }
    “`

    Con este cambio, el script de Python ya no debería encontrar el error de falla de segmentación.

Comments are closed.