删除由 boost::python 暴露的 std::vector 中的一个指针
Posted
技术标签:
【中文标题】删除由 boost::python 暴露的 std::vector 中的一个指针【英文标题】:delete a pointer in std::vector exposed by boost::python 【发布时间】:2015-02-22 02:38:43 【问题描述】:我有这两个类:
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)
;
AddEntity
和RemoveEntity
的实现是:
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
的部分和查找目标实体是成功的,但是它在RemoveEntity
的delete *
指令处崩溃(我通过在每一行代码后添加日志指令来检查这些)。这是我在 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 *>
的曝光不正确,但是我该如何纠正呢?
【问题讨论】:
为什么你在 C++ 和 Python 中使用了 html/javascript 可运行代码 sn-p 块? 你能做一个测试用例吗?也许抽象掉所有的 Python?你的调试器说了什么? 您的代码中没有证据表明您的实体是动态分配的,因此调用delete
会导致非动态分配条目的未定义行为。
哦,谢谢 PaulMcKenzie 和 Yakk,也许我知道它出了什么问题。
【参考方案1】:
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
类 * 仍然认为它拥有 Entity
,因为它无法被告知您已将所有权转移。但是现在它拥有一个无效的指针。
崩溃发生在删除时,因为 C++ 没有管理该内存——python 是。它不使用 C++ 堆。
您需要对 C++ 代码中的所有权和生命周期管理进行更牢固的设计。永远不要 delete
你没有 new
,python 案例中的 C++ 代码永远不会 new
ed Entity
。
【讨论】:
也就是说,例如我需要一个成员函数,它可以新建一个Entity并在C++中返回它的点,然后把这个点给AddEntity对吗? @Ddavid 您需要停止通过原始 C++ 指针传递对象的所有权。如果您拥有所有权,请使用类型化的拥有智能指针。然后让接口在 Python 中工作。以上是关于删除由 boost::python 暴露的 std::vector 中的一个指针的主要内容,如果未能解决你的问题,请参考以下文章
用 boost.python 暴露 std::vector<double>