pybind11和std :: vector-如何使用胶囊释放数据
Pybind11 and std::vector -- How to free data using capsules?
i具有返回 std::vector
的C 函数原始数据阵列。
当前尝试
在此井井有条中,因此回答作者演示了如何确保在Numpy数组的参考数为零时,在C 中创建的原始数据阵列被适当释放。我试图使用std::vector
改写一个版本:
// aside - I made a templated version of the wrapper with which
// I create specific instances of in the PYBIND11_MODULE definitions:
//
// m.def("my_func", &wrapper<int>, ...)
// m.def("my_func", &wrapper<float>, ...)
//
template <typename T>
py::array_t<T> wrapper(py::array_t<T> input) {
auto proxy = input.template unchecked<1>();
std::vector<T> result = compute_something_returns_vector(proxy);
// give memory cleanup responsibility to the Numpy array
py::capsule free_when_done(result.data(), [](void *f) {
auto foo = reinterpret_cast<T *>(f);
delete[] foo;
});
return py::array_t<T>({result.size()}, // shape
{sizeof(T)}, // stride
result.data(), // data pointer
free_when_done);
}
观察到的问题
但是,如果我从python调用它,我会观察到两件事:(1)输出阵列中的数据是垃圾,(2)当我手动删除numpy阵列时,我会收到以下错误(sigabrt):
python3(91198,0x7fff9f2c73c0) malloc: *** error for object 0x7f8816561550: pointer being freed was not allocated
我的猜测是,这个问题与" delete[] foo
"行有关,该行可能是将foo
设置为result.data()
的行为。这不是分配std::vector
的方法。
可能的解决方案
一种可能的解决方案是创建T *ptr = new T[result.size()]
并将result
的内容复制到此原始数据数组。但是,我有结果可能很大,我想避免将所有时间分配和复制。(但也许不如我认为的那样长。)
另外,我对std::allocator
了解不多,但是也许有一种方法可以分配输出矢量外部所需的原始数据阵列 compute_something_returns_vector()
函数调用,然后丢弃std::vector
,然后保留,保留基础原始数据数组?
最终选项是重写compute_something_returns_vector
。
在与同事进行离线讨论之后,我解决了问题。我不想犯下如此人造的pas,所以我不会接受自己的答案。但是,为了将其作为信息目录,我想在此处为他人提供答案。
问题很简单:result
是堆栈分配的,需要分配堆,以便free_when_done
可以拥有所有权。以下是一个示例修复:
{
// ... snip ...
std::vector<T> *result = new std::vector<T>(compute_something_returns_vector(proxy));
py::capsule free_when_done(result, [](void *f) {
auto foo = reinterpret_cast<std::vector<T> *>(f);
delete foo;
});
return py::array_t<T>({result->size()}, // shape
{sizeof(T)}, // stride
result->data(), // data pointer
free_when_done);
}
我还能够使用不需要使用free_when_done
函数的std::unique_ptr
实现解决方案。但是,我无法使用任何一种解决方案运行Valgrind,因此我不能100%确定矢量持有的内存已适当释放。(Valgrind Python对我来说是一个谜。)对于完整性,下面是std::unique_ptr
方法:
{
// ... snip ...
std::unique_ptr<std::vector<T>> result =
std::make_unique<std::vector<T>>(compute_something_returns_vector(proxy));
return py::array_t<T>({result->size()}, // shape
{sizeof(T)}, // stride
result->data()); // data pointer
}
但是,我能够检查在Python和C 代码中分配的向量的地址,并确认没有进行compute_something_returns_vector()
的输出副本。
- 我可以使用哪种数据结构来释放连续内存中的内存?
- 如果一个变量在它之前释放了另一个(相同的数据类型)变量,如何将其分配给内存?
- 向量中的数据何时释放
- QTCPSOCTED数据传输在读取缓冲区已满时停止,并且在释放时不会恢复
- 如何防止ptr_map在插入失败时释放数据
- pybind11和std :: vector-如何使用胶囊释放数据
- 我试图释放数据的某些部分,并用特定的整数值标记其休息,以表明它不是有效的指针.(不是数组)
- C++ 在覆盖新运算符和删除运算符时不释放数据
- 数据结构中的双重释放或损坏
- 即使在返回值之前释放后,数据仍在指针中仍然存在
- 从 C++ 中的字符*释放数据
- 释放包含数据的缓冲区
- 当类对象完成时,是否为 C++ 类的数据成员动态分配的内存会释放
- 自动释放 Mat 中的用户数据.可能吗
- 为什么在为常量数据释放内存时需要const_cast
- 如何在运行时确定数据的大小(已分配和已释放)
- 在释放数据之前,请先将阵列填满
- opengl在调用glBufferData后释放内存会导致数据不显示
- 这会正确释放数据吗?
- 是否在释放或析构函数中删除com对象的实例数据?