删除 boost::python 公开的 std::vector 中的指针

delete a pointer in std::vector exposed by boost::python

我有这两个类:

typedef std::vector<Entity *> EntityPtrVector;

class A
{
private:
    EntityPtrVector entity_vector;

public:
    void AddEntity(Entity *);
    void RemoveEntity(std::string);
};

class Entity
{
private:
    std::string name_;

public:
    Entity();
    Entity(std::string);

    std::string GetName(void) const { return name_; }
    void SetName(const std::string& name) { name_ = name; }
};

我通过 boost::python 像这样公开它们:

BOOST_PYTHON_MODULE(my_lib)
{
    using namespace boost::python;

    class_<EntityPtrVector>("EntityPtrVector")
        .def(vector_indexing_suite<EntityPtrVector>());

    class_<A>("A", init<std::string>())
        .def("AddEntity", &A::AddEntity)
        .def("RemoveEntity", &A::RemoveEntity)
    ;

    class_<Entity>("Entity", init<std::string>())
        .add_property("name", &Entity::GetName, &Entity::SetName)
    ;
}

AddEntityRemoveEntity的实现是:

void Game::AddEntity(Entity *E)
{
    entity_vector.push_back(E);
}

void Game::RemoveEntity(std::string entity_name)
{
    EntityPtrVector::iterator entity_ptr;

    // Find the entity with the input name
    for(entity_ptr = entity_vector.begin(); entity_ptr != entity_vector.end(); ++entity_ptr)
    {
        if((*entity_ptr)->GetName() == entity_name)
        {
            break;
        }
    }
    // Remove the target entity
    if(entity_ptr != entity_vector.end())
    {
        delete *entity_ptr;
        entity_vector.erase(entity_ptr);
    }
}

我已经检查过它可以在 C++ 下工作而没有暴露给 python。在python中,AddEntity和查找目标实体的部分是成功的,但是它在RemoveEntitydelete *指令处崩溃(我通过在每行之后添加日志指令来检查这些的代码)。这是我在 python:

中的测试代码
import my_lib

test_a = my_lib.A("Test A")
test_e = my_lib.Entity("Test Entity")

test_a.AddEntity(test_e)
test_a.RemoveEntity("Test Entity")

我想也许我 std::vector<Entity *> 的曝光不正确,但我该如何纠正呢?

test_e = my_lib.Entity("Test Entity")

创建一个拥有 C++ Entity 的 Python 对象。它管理生命周期。

test_a.AddEntity(test_e)

这里我们将test_e包裹的C++对象传递给test_a包裹的C++对象。 C++ 对象存储在 A.

的向量中
test_a.RemoveEntity("Test Entity")

这会删除您在上面添加的 Entity。但是,test_e class * 仍然认为它拥有 Entity,因为没有办法告诉它您已转让所有权。但现在它拥有一个无效指针。

崩溃发生在删除时,因为 C++ 不管理该内存 -- python 是。它不使用 C++ 堆。

您需要在 C++ 代码中对所有权和生命周期管理进行更严格的设计。永远不要 delete 你没有 new 的东西,并且 python 案例中的 C++ 代码永远不会 new 编辑 Entity.