代码在放入类的不同函数中时崩溃。

huangapple go评论52阅读模式
英文:

Code crashes when put into separate functions within a class

问题

这段代码存在两个版本,第一个版本将所有内容放在类的__init__函数中,而第二个版本将内容分成两个函数:viewerInitviewerRefresh。第一个版本正常工作,但第二个版本在鼠标悬停在Pangolin查看器窗口时崩溃。

问题可能与Python的垃圾收集机制有关。在第二个版本中,您将初始化代码移到了viewerInit函数中,但是在__init__函数完成后,viewerInit函数的局部变量可能被垃圾收集,导致一些资源被释放或者指针失效。这可能是导致程序崩溃的原因。

您可以尝试在viewerInit函数内部添加self前缀来确保相关变量是实例变量,而不是局部变量,以防止它们被垃圾回收。例如:

self.pm = pango.ProjectionMatrix(640, 480, 420, 420, 320, 240, 0.1, 1000)
self.mv = pango.ModelViewLookAt(-0, 0.5, -3, 0, 0, 0, pango.AxisY)

这样可能会解决程序崩溃的问题。如果问题仍然存在,请考虑进一步调查与资源管理和垃圾收集相关的问题。

英文:

I've ran into an odd situation in Python where code works if I put everything in the __init__ function of a class, but if I break it up into functions within the class, the otherwise identical code crashes. Here is my current example:

This works:

# SimpleDisplay5.py

import faulthandler
import pypangolin as pango
import OpenGL.GL as gl
import numpy as np
import time

class Display3D(object):

    def __init__(self):
        self.win = pango.CreateWindowAndBind('Pangolin Viewer', 640, 480)
        gl.glEnable(gl.GL_DEPTH_TEST)

        pm = pango.ProjectionMatrix(640, 480, 420, 420, 320, 240, 0.1, 1000)
        mv = pango.ModelViewLookAt(-0, 0.5, -3, 0, 0, 0, pango.AxisY)
        self.s_cam = pango.OpenGlRenderState(pm, mv)

        ui_width = 180

        handler = pango.Handler3D(self.s_cam)
        self.d_cam = (
            pango.CreateDisplay()
            .SetBounds(
                pango.Attach(0),
                pango.Attach(1),
                pango.Attach.Pix(ui_width),
                pango.Attach(1),
                -640.0 / 480.0,
            )
            .SetHandler(handler)
        )

        self.points = np.random.uniform(-1.0, 1.0, (100, 3)).astype(np.float32)

        gl.glPointSize(5)
        gl.glColor3f(1.0, 0.0, 0.0)  # red
        
        while not pango.ShouldQuit():
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

            self.d_cam.Activate(self.s_cam)

            pango.glDrawPoints(self.points)

            pango.FinishFrame()
        # end while
    # end function

# end class

def main():
    faulthandler.enable()

    np.set_printoptions(suppress=True)

    disp3d = Display3D()

    while True:
        time.sleep(0.5)
    # end while

# end function

if __name__ == "__main__":
    main()

This crashes with a segmentation fault:

# SimpleDisplay6.py

import faulthandler
import pypangolin as pango
import OpenGL.GL as gl
import numpy as np
import time

class Display3D(object):

    def __init__(self):
        self.viewerInit()

        self.viewerRefresh()
    # end function

    def viewerInit(self):
        self.win = pango.CreateWindowAndBind('Pangolin Viewer', 640, 480)
        gl.glEnable(gl.GL_DEPTH_TEST)

        pm = pango.ProjectionMatrix(640, 480, 420, 420, 320, 240, 0.1, 1000)
        mv = pango.ModelViewLookAt(-0, 0.5, -3, 0, 0, 0, pango.AxisY)
        self.s_cam = pango.OpenGlRenderState(pm, mv)

        ui_width = 180

        handler = pango.Handler3D(self.s_cam)
        self.d_cam = (
            pango.CreateDisplay()
            .SetBounds(
                pango.Attach(0),
                pango.Attach(1),
                pango.Attach.Pix(ui_width),
                pango.Attach(1),
                -640.0 / 480.0,
            )
            .SetHandler(handler)
        )

        self.points = np.random.uniform(-1.0, 1.0, (100, 3)).astype(np.float32)

        gl.glPointSize(5)
        gl.glColor3f(1.0, 0.0, 0.0)  # red
    # end function

    def viewerRefresh(self):
        while not pango.ShouldQuit():
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

            self.d_cam.Activate(self.s_cam)

            pango.glDrawPoints(self.points)

            pango.FinishFrame()
        # end while
    # end function
# end class

def main():
    faulthandler.enable()

    np.set_printoptions(suppress=True)

    disp3d = Display3D()

    while True:
        time.sleep(0.5)
    # end while

# end function

if __name__ == "__main__":
    main()

Specifically, the 2nd program crashes when I mouse over the Pangolin viewer window. Here is the terminal output for the 2nd program:

$ python3 SimpleDisplay6.py 
Fatal Python error: Segmentation fault

Current thread 0x00007f4384b05740 (most recent call first):
  File "SimpleDisplay6.py", line 54 in viewerRefresh
  File "SimpleDisplay6.py", line 14 in __init__
  File "SimpleDisplay6.py", line 64 in main
  File "SimpleDisplay6.py", line 73 in <module>
Segmentation fault (core dumped)

Line 54 in the 2nd program is:

        pango.FinishFrame()

Note that the only difference between the 2 programs is in the 2nd, I divided up the __init__ content into 2 separate functions. Can somebody explain what is going on here or how this is even possible? Thinking of how this would break down into CPython, I would have figured it should have been identical.

I did post a question in the Pangolin viewer repo https://github.com/stevenlovegrove/Pangolin/issues/861, but the more I consider the situation I'm not sure this is a Pangolin concern since the 1st example works.

Moreover, I recall something very similar happening before when I attempted to call OpenCV functions from within a Qt frame (I don't have the code for that currently however).

I should probably also mention I'm aware the while True in main() is never reached in either program, I left that code in since my eventual plan was to start the Pangolin viewer on a separate thread when I get this current problem worked out.

Any suggestions as to the cause of this or what I should check next?

答案1

得分: 1

在这个 Python 扩展中,我完全不了解,但有间接证据表明,在调用 pango.glDrawPoints 和/或 pango.FinishFrame 时,pango.ProjectionMatrixpango.ModelViewLookAtpango.Handler3D 中的一个或多个对象必须仍然处于 活动状态。这可以说是 pango 中的一个 错误;通常的期望是只要存在 任何 相关的 Python 对象,它就会使这些 Python 对象(或它们的底层 C++ 对象)保持活动状态。

英文:

With the loud disclaimer that I know nothing about this Python extension, the circumstantial evidence is that one or more of the pango.ProjectionMatrix, pango.ModelViewLookAt, and pango.Handler3D objects must still be alive during the calls to pango.glDrawPoints and/or pango.FinishFrame. This is arguably a bug in pango; the usual expectation is that it keeps the Python objects (or their coordinate C++ objects) alive so long as any relevant Python object is alive.

huangapple
  • 本文由 发表于 2023年4月17日 00:35:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定