You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pybind11存储numpy数组指针调用时指针失效崩溃问题求助

问题原因

崩溃的核心原因是你存储的numpy数组指针对应的内存被提前释放,具体有两个诱因:

  1. 测试代码中传入init_ptrs的第二个参数torchTensorB.numpy() * 3840是临时生成的numpy数组,且如果数组不满足C风格连续的要求,pybind11会隐式创建临时数组副本完成类型转换,py::keep_alive无法正确延长这类隐式生成的临时对象的生命周期,函数调用结束后临时数组被销毁,m_ptrB直接变成悬空指针。
  2. C++类只存储了裸指针,没有持有对应numpy数组的引用,完全依赖py::keep_alive保证内存有效性,本身稳定性极低,很容易出现指针悬空问题。
解决方案

方案一(推荐,最稳妥)

修改C++类,直接持有py::array_t作为成员变量,自动管理数组生命周期,不需要依赖py::keep_alive:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <iostream>

namespace py = pybind11;

class Foo
{
public:
  void initPtrs( py::array_t<int32_t, py::array::c_style> pyAryA,
                 py::array_t<float32_t, py::array::c_style> pyAryB
                )
  {
    // 保存py::array实例,自动增加引用计数,保证内存不会被提前释放
    m_aryA = pyAryA;
    m_aryB = pyAryB;
    m_ptrA = static_cast<int32_t*>(m_aryA.request().ptr);
    m_ptrB = static_cast<float32_t*>(m_aryB.request().ptr);
  }
  
  void doSomethingWithPtrs()
  {
     std::cout << m_ptrB[0] << std::endl;
  }
  
 private:
   py::array_t<int32_t, py::array::c_style> m_aryA;
   py::array_t<float32_t, py::array::c_style> m_aryB;
   int32_t* m_ptrA = nullptr;
   float32_t* m_ptrB = nullptr;
};

绑定代码可以直接移除py::keep_alive配置:

PYBIND11_MODULE(bar,m)
{
py::class_<Foo>(m,"Foo")
  .def(py::init<>())
  .def( "init_ptrs", &Foo::initPtrs )
  .def( "do_something_with_ptrs", &Foo::doSomethingWithPtrs );
}

方案二(不修改C++类结构)

如果不能修改原有C++类,需要从Python调用侧做兼容:

  1. 不要直接传入临时数组,先把运算结果存到Python变量持有引用,同时显式转换为C风格连续数组,避免pybind11生成隐式临时副本:
def test( aryA, torchTensorB ):
  my_foo = bar.Foo()
  # 显式存为变量 + 转C风格连续数组
  aryB = (torchTensorB.numpy() * 3840).copy(order='C')
  my_foo.init_ptrs( aryA, aryB )
  my_foo.do_something_with_ptrs()
  # 注意:my_foo销毁前,aryA、aryB不能被Python回收
  1. 你原本的py::keep_alive用法是正确的,py::keep_alive<1,2>表示只要Foo实例(参数1)存活,传入的第二个参数就不会被回收,符合需求。

内容的提问来源于stack exchange,提问作者user16372530

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 14:18:03