pybind / pybind/pybind11

[BUG]: Segmentation fault on Windows with abstract classss

Open
#3,217 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Required prerequisites
Problem description

A have two abstract C++ class: Door and Knob. Door returns a Knob with Door::GetKnob. The knob can be pulled with Knob::Pull(). Door successfully calls Door::GetKnob and gets a non-null knob, but the code crashes when Knob::Pull is called.

Reproducible example code

C++

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

namespace py = pybind11;

int simple_add(int i, int j) {
    return i + j;
}

class Knob {
 public:
  virtual void Pull() = 0;
};

class Door {
 public:
  virtual std::string_view Name() = 0;
  virtual Knob& GetKnob() = 0;
};

void open_door(Door& door) {
  std::string_view name = door.Name();
  std::cout << name << std::endl;
  Knob& knob = door.GetKnob();
  std::cout << "Got the knob" << std::endl;
  knob.Pull();
  std::cout << "Pulled the knob" << std::endl;
}

class PyKnob : public Knob {
 public:
  using Knob::Knob;
  void Pull() {
    PYBIND11_OVERRIDE_PURE(void, Knob, Pull);
  }
};

class PyDoor : public Door {
 public:
  using Door::Door;
  std::string_view Name() {
    PYBIND11_OVERRIDE_PURE(std::string_view, Door, Name);
  }
  Knob& GetKnob() {
    PYBIND11_OVERRIDE_PURE(Knob&, Door, GetKnob);
  }
};

PYBIND11_MODULE(pybind_test, m) {
  m.def("simple_add", &simple_add);
  m.def("open_door", &open_door);
  py::class_<Knob, PyKnob>(m, "Knob")
    .def(py::init<>())
    .def("Pull", &Knob::Pull);
  py::class_<Door, PyDoor>(m, "Door")
    .def(py::init<>())
    .def("Name", &Door::Name)
    .def("GetKnob", &Door::GetKnob);
}

Python

import pybind_test

print(pybind_test.simple_add(3, 4))

class MyKnob(pybind_test.Knob):
    def __init__(self):
        pybind_test.Knob.__init__(self)

    def Pull(self):
        print("Hey!")

class MyDoor(pybind_test.Door):
    def __init__(self, name):
        pybind_test.Door.__init__(self)
        self.name = name

    def Name(self):
        return self.name
    
    def GetKnob(self):
        return MyKnob()

print("Opening")
pybind_test.open_door(MyDoor("I'm a door."))
print("Done")

Output

7
Opening
I'm a door.
Got the knob

Program crashes at this point. (while calling knob.Pull();)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the provided C++ and Python reproducer on Windows, then inspect pybind11's virtual override and reference-return handling around Door::GetKnob and Knob::Pull. Done means the example no longer segfaults and reaches the Python MyKnob.Pull implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.