【问题标题】:cython - segmentation fault when assigning c++ class instance pointerscython - 分配 C++ 类实例指针时出现分段错误
【发布时间】:2013-10-23 20:41:30
【问题描述】:

我是 cython 的新手,正在尝试用 cython 包装一些现有的 c++ 代码,以便它们可以在 python 中使用。我的问题的一个非常简化的版本如下。

啊.h

#ifndef A_H
#define A_H
class A
{
public:
    int value;
    A(int x);
    void printA();
};
#endif

A.cpp

#include <iostream>
#include "A.h"
A::A(int x)
{
    std::cout<<"entering A constructor"<<std::endl;
    value = x;
    std::cout<<"exiting A constructor"<<std::endl;

}
void A::printA()
{
    std::cout<<"print value in A :"<<value<<std::endl;
}

cmd.h

#include "A.h"
class CMD
{
public:
    A *a;
    void init(int x);
    void test();

};  

cmd.cpp

#include "cmd.h"
#include <iostream>
void CMD::init(int x)
{
    std::cout<<"start initializing A"<<std::endl;
    a = new A(x); // this line is causing the segmentation fault
    std::cout<<"end initializing A"<<std::endl;
}

void CMD::test()
{
    std::cout<<"start printing A"<<std::endl;
    a->printA();
    std::cout<<"end printing A"<<std::endl;

}

PyCMD.pyx

cdef extern from "cmd.h":
    # cdef cppclass A:
    #     A(int x)
    cdef cppclass CMD:
        # A *a
        CMD()
        void init(int x)
        void test()

cdef class PyCMD:
    cdef CMD *thisptr
    def __cint__(self):
        self.thisptr = new CMD()
    def __dealloc__(self):
        del self.thisptr
    def init(self, x):
        self.thisptr.init(x)
    def test(self):
        self.thisptr.test()

setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("cmdtest", ["PyCMD.pyx","cmd.cpp","A.cpp"],language='c++')]
)

helloword.py

from cmdtest import *
d = PyCMD()
d.init(10)
d.test()

程序非常简单。 A 类只是有一个构造函数和一个打印 A 中值的方法。 cmd 类在其 init() 方法中创建 A 的实例,并在 test() 中调用 A 的 printA() 方法。 cython 代码基本上创建了一个 cdef 类 PyCMD,它模仿了 cmd 类中可用的所有方法。当我运行 helloworld.py 时,输出如下。

start initializing A
entering A constructor
exiting A constructor
[1]    11689 segmentation fault  {my_python_path}

显然,在分配 A 实例的指针时会发生分段错误。然后我写了一个 main.cpp 来确保至少 c++ 代码是可靠的。

main.cpp

#include "cmd.h"
int main()
{
    CMD *cmd = new CMD();
    cmd->init(10);
    cmd->test();
}

输出看起来不错。

start initializing A
entering A constructor
exiting A constructor
end initializing A
start printing A
print value in A :10
end printing A

问题应该出在 cython 上,但我不知道问题出在哪里。

我非常感谢任何帮助。

【问题讨论】:

  • 这不可能是你的实际代码,因为在 setup.py 中有一个明显的SyntaxError。有一个明显的解决方法,但很高兴知道我们正在调试您正在运行的相同代码,而不是可能有或可能没有相同问题的类似代码。
  • @abarnert 感谢您指出这一点。我已经解决了这个问题并测试了所有代码。现在应该没有错误了。

标签: c++ python segmentation-fault cython


【解决方案1】:

问题是您没有 PyCMD 的初始化程序,因此 thisptr 未初始化。

您可以看到这是您在 Cython 代码中的任意位置打印出self.thisptr,或者在 C++ 代码中打印出this

您确实有一个看起来类似于初始化程序的函数……但因为它被称为 __cint__ 而不是 __cinit__,所以它不是。

所以,等效的 C++ 代码是这样的:

#include "cmd.h"
int main()
{
    CMD *cmd;
    cmd->init(10);
    cmd->test();
}

...给出完全相同的段错误。

【讨论】:

  • 救命稻草!我花了几个小时试图找到问题,你马上就发现了!非常感谢!
  • @pippo:作为参考,我发现它的方式是在每个函数(C++、Cython 和 Python)中添加打印,并注意到从未调用过 __cinit__,这让我想知道为什么,此时我意识到消息中的字符串与方法名称不匹配。但实际上,这可能是任何新鲜眼光都可以工作的情况之一,而我的只是你的代码的第一眼新鲜眼光。
  • 好点!再次感谢您让我知道您是如何发现它的。
猜你喜欢
  • 2020-02-18
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 2018-07-20
  • 2020-12-27
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
相关资源
最近更新 更多