Cython:存储指针时Python/C++之间的内存所有权问题

2024-09-30 22:22:37 发布

您现在位置:Python中文网/ 问答频道 /正文

< Python/C++代码使用Cython有内存所有权问题。我不知道什么是解决这个问题的最好办法。所以我很感激你的帮助。在

我的策略如下:

  1. 创建具有GET / SET成员的C++ NETFIN数据结构。在
  2. 用Python填充这个数据结构(从文件解析数据并完成SqLiteDB查找)。因此,我需要将NetInfo进行cythozing。在
  3. 将NETFION对象传递给C++处理程序,以对它们进行操作。这些也将被cythonized。在

对于NetInfo对象,我需要存储指向其他NetInfo对象的指针,以指示两个对象之间的交互。在

<>我的(相关)C++代码如下:

struct NetInfoData;
class NetInfo {
public:
    NetInfo();
    NetInfo(NetInfo const& rhs);
    virtual ~NetInfo();
    ...
    std::vector<NetInfo*> getBridgedNets() const;
    void addBridgedNet(NetInfo const* ni);  
protected:
      NetInfoData* data_;
};
struct NetInfoData
{
     std::string name;
     ...
     std::vector<NetInfo*>  bridged_nets; <-- NOTE: Storing pointers.
};
NetInfo::NetInfo()
    : data_(0)
{
    std::cout << "Constructor " << this << std::endl;
    data_ = new NetInfoData();
}
NetInfo::~NetInfo()
{
    std::cout << "Destructor " << this << std::endl;
    delete data_;
}
NetInfo::NetInfo(NetInfo const& rhs)
    : data_(0)
{
    std::cout << "Copy constructor " << this << std::endl;
    data_ = new NetInfoData();
    data_->name = rhs.data_->name;
    ...
    data_->bridged_nets = rhs.data_->bridged_nets;
}
std::vector<NetInfo*>
NetInfo::getBridgedNets() const
{
    return data_->bridged_nets;
}

void
NetInfo::addBridgedNet(NetInfo* n)
{
    data_->bridged_nets.push_back(n);
}

我的(相关)Cython代码如下。它编译/工作正常。在

^{pr2}$

现在我的Python伪代码如下:

import PyNetInfo as NetInfo

a = NetInfo()               # Create a
Update data members of a    # Populate a

tmp = NetInfo(a)     # Call copy constructor of a
for n in xrange(5):  # a interacts with five other NetInfo objects so create and call them to a via add_bridged_net() 
   x = NetInfo(tmp)  # Call copy constructor to make copy of tmp (not a!!)
   Update data members of x

   a.add_bridged_net(x)   # Store pointer to x in a (a is updated!)

有问题的代码是x=NetInfo(tmp)。在第二次迭代中,分配给x的旧内存将被释放,因为x现在指向一个新对象。这将导致a现在包含无效指针。在

样本运行:

create a
Constructor 0x101ecd0

create tmp
Copy constructor 0xd71d30

create bridge x
Copy constructor 0xd71bb0
add bridged net:  

create bridge x
Copy constructor 0xc9f740
Destructor 0xd71bb0   <--- Destructor on old x is called due to reassignment which causes a to contain an invalid pointer (hence, eventually segfault)
add bridged net:

我不太清楚如何管理内存来解决这个问题。有人能帮忙吗?在

我在想也许使用共享指针?所以在我的C++代码中,我说

typedef std::shared_ptr<NetInfo> NetInfoShPtr;

然后

std::vector<NetInfo*> bridged_nets -> std::vector<NetInfoShPtr> bridged_nets;

但我不知道该怎么办。这个行吗?还是有其他的(更容易的?)怎么了?谢谢你的建议。在


Tags: to对象代码datacreatetmpstdvector
2条回答

当你这么做的时候

a.add_bridged_net(x)

不会存储对x的引用,只将指向NetInfo实例的指针添加到向量中。因为没有引用Python对象^ {< CD1> },所以^ {CD1}}将被释放,因此相应的指针指向C++ +{ },即,向量中有一个指针指向一个被释放的对象。在

我能够使用共享指针来解决这个问题(让它来完成管理的所有脏活)。唯一的麻烦是现在需要大量使用deref(本公司在Cython的每一个地方都调用C++的GET/SETION方法:在

C++变化:

class NetInfo
typedef std::shared_ptr<NetInfo> NetInfoShPtr;

class NetInfo {
public:
    NetInfo();
    NetInfo(NetInfo const& rhs);
    virtual ~NetInfo();
    ...
    std::vector<NetInfoShPtr> getBridgedNets() const;
    void addBridgedNet(NetInfoShPtr const& ni);  
protected:
      NetInfoData* data_;
};

赛顿变化:

^{pr2}$

相关问题 更多 >