【发布时间】:2021-11-12 11:43:56
【问题描述】:
我已经为此工作了几周,无法在我的代码库之外制作可重现的示例。这就是为什么我需要帮助!我不确定这是否是 pybind11 或犰狳的问题。 Carma 没有问题,因为它发生在没有进行转换的情况下。
编辑:This actually does appear to be a bug in Carma and my MRE is working.
我一直试图将其归结为MRE and have been unsuccessful。我将在这里解释我所知道的,但由于这不足以重现错误,所以我最需要的是一些关于在哪里查找的想法。这基本上是一个非常难以重现的内存损坏错误(堆损坏,Windows fatal exception: code 0xc0000374)。当我有一个未初始化的矩阵 A 并为其分配一个足够大的矩阵以使犰狳获取内存时,似乎会发生这种情况。释放该内存时会发生崩溃。
我在 Windows 10 上,使用 Armadillo 10.6.2 和 pybind11 v2.7.1,使用 Clang 11 编译。
// mat_container.cpp
#include "mat_container.h"
MatrixContainer::MatrixContainer(size_t d) {
A = arma::Mat<double>(d, d, arma::fill::eye);
std::cerr << "filled arma matrix\n";
}
绑定代码
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <armadillo>
#include <carma>
#include "mat_container.h"
PYBIND11_MODULE(example, m) {
py::class_<MatrixContainer>(m, "MC").def(py::init<size_t, bool>())
.def_readwrite("A", &MatrixContainer::A);
}
触发崩溃我需要做的就是通过 Python 调用 example.MC(11) 并在释放成员变量的矩阵析构函数(不是分配给它的临时变量)中的内存时崩溃。犰狳在崩溃前调试消息:
@ __cdecl arma::Mat<double>::~Mat(void) [eT = double] [this = 000001569470DBA0]
Mat::destructor: releasing memory
在我的attempted MRE 中,我尝试使用在单独的库中编译的这个 MatrixContainer 类的绑定代码来重现相同的结构。我不知道可能缺少什么,所以我的 MRE 不会重现该错误。
奇怪的事情
- 仅在从 pybind11 调用时发生,而不是纯 C++
- 仅当包含矩阵的类的构造函数位于单独编译的源文件中时才会发生。当构造函数在头文件中时不会发生。
- 仅在将非标识(例如
np.ones但不是np.eye)矩阵分配给对象的矩阵成员变量时才会发生。 但这只会发生在我的源代码中的一个类上,而不是我创建的较小的测试类上! - 仅当 A 大到足以让犰狳获取内存而不是使用本地内存时才会发生
- 在分配 A 之前使用
set_size()设置 A 的大小并不能解决问题 - 这似乎是犰狳特有的,当犰狳释放内存时(使用
ARMA_EXTRA_DEBUG确认),因为当我使用另一个具有动态分配内存的类(如矢量)时,我没有收到类似的错误
当A使用获取的内存,被使用本地内存的矩阵替换时,会发生崩溃
mc = MC(11)
mc.A = np.eye(3)
在崩溃前的 Arma 调试消息,因为正在分配 mc.A:
@ void __cdecl arma::Mat<double>::init_warm(arma::uword, arma::uword) [eT = double] [in_n_rows = 3, in_n_cols = 3]
Mat::init(): releasing memory
但不是在相反的情况下;这运行成功。它不会因为 A 被销毁而释放获取的内存而崩溃:
mc = MC(3)
mc.A = np.eye(11)
当一个 11x11 A 被 numpy 中的另一个 11x11 矩阵替换时,崩溃再次是 Mat::destructor: releasing memory,就像第一个示例中没有来自 Python 的赋值一样。 我从这些示例中得出的结论是,当将由 Carma(不是 Armadillo 直接)准备的获取内存矩阵分配给本地内存 A 时,可以避免崩溃。
更新: 仍在处理此问题,但看起来代码失败了,因为 arma_extra_code 已打开(它不在 MRE 中)。罪魁祸首似乎是ARMA_ALIEN_MEM函数,设置here
【问题讨论】:
标签: python c++ armadillo pybind11