【问题标题】:Bug occurs only when compiling with -O3错误仅在使用 -O3 编译时出现
【发布时间】:2012-01-14 18:50:21
【问题描述】:

在使用 GLFW 和 Cython 制作 OpenGL 工具包时,我偶然发现了一个非常非常奇怪的问题。我创建了以下文件 pxd 文件(相当大,所以我记下了它):

https://gist.github.com/1441970

接下来我有这个包装代码(非常简化以显示问题的核心)。

pygrafix.window 模块:

from pygrafix.c_headers.glfw cimport * # this is the pxd file

glfwInit()

_window = None

cdef void _mouse_scroll_callback_handler(int pos):
    if _window._mouse_scroll_callback:
        _window._mouse_scroll_callback(_window, pos)

cdef class Window:
    cdef public object _mouse_scroll_callback

    def __cinit__(self):
        global _window
        self._mouse_scroll_callback = None

        _window = self

    def __init__(self, int width = 0, int height = 0):
        glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)
        glfwSetMouseWheelCallback(<GLFWmousewheelfun> &_mouse_scroll_callback_handler)
        print("TEST LOCATION ONE")

    def is_open(self):
        return glfwGetWindowParam(GLFW_OPENED)

    def flip(self):
        glfwSwapBuffers()

    def set_mouse_scroll_callback(self, func):
        self._mouse_scroll_callback = func

还有这个主文件:

from pygrafix import window

window = window.Window(800, 600)
print("TEST LOCATION TWO")

def on_scroll(window, pos):
    print(pos)

window.set_mouse_scroll_callback(on_scroll)

while window.is_open():
    window.flip()

最后我是这样编译的:

cython.py -o pygrafix/window.cy.c pygrafix/window.pyx
gcc -O3 -shared -DGLFW_DLL -IC:\Python27\include pygrafix/window.cy.c -o pygrafix/window.pyd -LC:\Python27\libs -lpython27 -lgfwldll

但它崩溃了(windows 说程序中有错误)。当我注释掉对glfwSetMouseWheelCallback 的调用时,它不会崩溃。 奇怪的是,如果我用 -O0 编译 它不会崩溃并且可以正常工作! 我对此完全感到困惑。我检查了 cython 输出的 C 代码,看起来没问题。 _mouse_scroll_callback_handler 属于 void (*)(int) 类型,指向它的指针可以很好地传递给 glfw。

其他怪事:

  • 这种情况只发生在 glfwSetMouseWheelCallback(或至少对我而言),例如 glwSetMousePosCallback 不会发生。
  • 如果我将 NULL 传递给glfwSetMouseWheelCallback,则没有问题。
  • 即使发生崩溃,TEST LOCATION ONE 仍会打印,但 TEST LOCATION 2 不会。
  • 如果我使用 -O3 -pg 编译它也可以工作

这可能是什么原因,正确的解决方法是什么(无需在 -O0 编译)?


其他琐事:

我在 MinGW 和 CPython 2.7.2 下使用 Windows 7 64 位、GLFW 2.7.2、Cython 0.15.1、GCC 4.6.1。

【问题讨论】:

  • 这很可能是(编译器的)优化错误
  • 你能发布回溯吗?我建议您使用其他内存分析器测试您的库。这可能是由于未初始化的内存,并导致这种奇怪的错误。
  • 为什么需要GLFWmousewheelfun 的演员表?那是可疑的。如果您用作回调的函数没有正确的类型来解释崩溃。
  • @sth:我不知道。否则我得到的警告是(沿线):Warning: expected GLFWmousewheelfun, got void (*)(int)。而GLFWmousewheelfun 被定义为typedef void(GLFWCALL* GLFWmousewheelfun)(int)GLFWCALL__stdcall 或类似的东西。
  • 再一次,如果您没有使用内存分析器进行测试(我不认识 Windows 上的任何人,但我正在考虑类似 valgrind),您可能会看到您做错了什么.例如,如果您在分配的内存之外的某处覆盖 3 个字节,您可能会擦除一些重要信息。也许 -O3、-pg、-O0 触发了不同的内存组织,并且您看不到错误/在崩溃中看到它。这里需要更深入的分析:)

标签: gcc cython glfw


【解决方案1】:

我终于找到了解决办法。问题是我没有在 Cython 中将 __stdcall 添加到回调函数中,也不知道它支持这个。

【讨论】:

    猜你喜欢
    • 2021-09-26
    • 1970-01-01
    • 2020-09-19
    • 2013-06-16
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多