英文:
OpenGL's glClear() causes Access Violation (0xc0000005) in Windows 64
问题
看一下这个用Go语言编写的超级简单的小测试案例OpenGL程序:
package main
import (
"runtime"
"./glfw"
gl "github.com/chsc/gogl/gl21"
)
func onExit (err error) {
glfw.Terminate()
if err != nil { panic(err) }
}
func main () {
runtime.LockOSThread()
err := glfw.Init()
if err != nil { panic(err) }
err = glfw.OpenWindow(1280, 720, 0, 0, 0, 0, 0, 0, glfw.Windowed)
if err != nil { onExit(err) }
err = gl.Init()
if err != nil || gl.GetError() != 0 { onExit(err) }
for glfw.WindowParam(glfw.Opened) == 1 {
gl.Viewport(0, 0, 1280, 720)
gl.ClearColor(1, 0, 0, 1)
gl.Clear(gl.COLOR_BUFFER_BIT) // THE CRASH
gl.Begin(gl.TRIANGLES)
gl.Color3f(1, 0, 0)
gl.Vertex3f(-1, -1, 0)
gl.Color3f(0, 1, 0)
gl.Vertex3f(0, 1, 0)
gl.Color3f(0, 0, 1)
gl.Vertex3f(1, -1, 0)
gl.End()
glfw.SwapBuffers()
if glfw.Key(glfw.KeyEsc) == 1 {
glfw.CloseWindow()
}
}
onExit(nil)
}
这个程序在Windows 7 64位和Go 1.0.1 64位下可以正常编译。
如果你去掉(或注释掉)gl.Clear(gl.COLOR_BUFFER_BIT)这一行,它也可以正常工作(OpenGL会绘制一个彩虹色的2D三角形,直到窗口关闭)。
然而,一旦调用gl.Clear,无论传入什么参数,它就会崩溃,Windows会提示“glfw-win.exe已停止工作...”,Windows事件查看器中有以下错误日志:
故障应用程序名称: glfw-win.exe,版本: 0.0.0.0,时间戳: 0x4f9f5ec5
故障模块名称: glfw-win.exe,版本: 0.0.0.0,时间戳: 0x4f9f5ec5
异常代码: 0xc0000005
故障偏移量: 0x0000000000012883
故障进程 ID: 0xd4c
故障应用程序启动时间: 0x01cd274e4c69a3d3
故障应用程序路径: C:\mytmp\glfw-win\glfw-win.exe
故障模块路径: C:\mytmp\glfw-win\glfw-win.exe
报告 ID: 8a5bacc0-9341-11e1-911a-d067e544ad7f
现在,有几个值得注意的点...
-
glfw包只是一个自定义包,暴露了与github.com/jteeuwen/glfw完全相同的API,但在内部使用LoadLibrary/GetProcAddress来使用glfw.dll,而不是编译时的CGO/GCC/LD链接 - 由于后者无法在64位Windows上工作,不确定是mingw64还是gcc还是cgo的问题。使用LoadLibrary/GetProcAddress调用我自定义的64位构建的glfw.dll工作得非常好。显然,这里的问题是与gl包的调用有关,而不是glfw。
-
gl包确实只是这个,没有修改。我尝试了一些LDFLAGS的修改,如-m64 -lmingw32 -Wl,/windows/opengl32.dll等,但没有任何区别,原始的代码和修改后的代码一样好,只要不调用gl.Clear(),所以我回到了原始的代码。当然,以后我会转向OpenGL 4.2。
-
使用Process Explorer,我可以看到我的进程是64位的,所有加载的DLL也都是64位的映像(包括opengl32.dll和glfw.dll)。
-
“可能是gl21包无法获取opengl32.dll导出的glClear()函数的有效地址吗?” - 不太可能:根据line 2926,如果是这种情况,我的gl.Init()调用将失败。
-
GPU驱动问题?更不太可能。最新的官方nVidia Quadro 5010M驱动程序296.35已安装。也尝试了“性能驱动程序”,但似乎是完全相同的驱动程序。根据nVidia控制面板,完全支持OpenGL 4.2(尽管opengl32.dll的日期是2009年 - 无论如何,对于我目前的2.1来说足够了)。此外,“Geeks3D GPU Caps Viewer”和“Shader Toy Mark”中的OpenGL着色器以及GLFW示例程序particles.exe都可以运行,它们都使用了glClear()。
-
使用gl42而不是gl21时,出现完全相同的问题,所以这也不是原因。
请注意,在这个例子中,所有其他的gl.SomeExportedFunc()调用都不会崩溃...
怎么办,如何继续?
如果只有gl.Clear()发生崩溃,而其他函数从不崩溃,我可以接受这个问题 - 我只会渲染全屏的四边形,自定义内容而已 - 但我在测试Win64时还处于早期阶段(在Linux64下有很多gl42代码可以正常工作,现在要“移植”到Win64),我担心以后的其他调用也会暴露出同样的问题,所以我现在报告这个问题。我很快就会发现哪些其他调用受到这个问题的影响。
英文:
Take a look at this super-simple small test-case OpenGL program written in Go:
package main
import (
"runtime"
"./glfw"
gl "github.com/chsc/gogl/gl21"
)
func onExit (err error) {
glfw.Terminate()
if err != nil { panic(err) }
}
func main () {
runtime.LockOSThread()
err := glfw.Init()
if err != nil { panic(err) }
err = glfw.OpenWindow(1280, 720, 0, 0, 0, 0, 0, 0, glfw.Windowed)
if err != nil { onExit(err) }
err = gl.Init()
if err != nil || gl.GetError() != 0 { onExit(err) }
for glfw.WindowParam(glfw.Opened) == 1 {
gl.Viewport(0, 0, 1280, 720)
gl.ClearColor(1, 0, 0, 1)
gl.Clear(gl.COLOR_BUFFER_BIT) // THE CRASH
gl.Begin(gl.TRIANGLES)
gl.Color3f(1, 0, 0)
gl.Vertex3f(-1, -1, 0)
gl.Color3f(0, 1, 0)
gl.Vertex3f(0, 1, 0)
gl.Color3f(0, 0, 1)
gl.Vertex3f(1, -1, 0)
gl.End()
glfw.SwapBuffers()
if glfw.Key(glfw.KeyEsc) == 1 {
glfw.CloseWindow()
}
}
onExit(nil)
}
This builds fine under Windows 7 64-bit with Go 1.0.1 64-bit.
It also works fine (OpenGL draws a single rainbow-colored 2D triangle until the Window is closed) IF you take out (or comment-out) the gl.Clear(gl.COLOR_BUFFER_BIT) line.
As soon as gl.Clear is called however (no matter what arguments are passed), it crashes, Windows informs me that "glfw-win.exe has stopped working..." and the Windows Event Viewer has the following error log for me:
Faulting application name: glfw-win.exe, version: 0.0.0.0, time stamp: 0x4f9f5ec5
Faulting module name: glfw-win.exe, version: 0.0.0.0, time stamp: 0x4f9f5ec5
Exception code: 0xc0000005
Fault offset: 0x0000000000012883
Faulting process id: 0xd4c
Faulting application start time: 0x01cd274e4c69a3d3
Faulting application path: C:\mytmp\glfw-win\glfw-win.exe
Faulting module path: C:\mytmp\glfw-win\glfw-win.exe
Report Id: 8a5bacc0-9341-11e1-911a-d067e544ad7f
Now, a couple of noteworthy points...
-
The glfw package is simply a custom package exposing the exact same API as github.com/jteeuwen/glfw but internally using LoadLibrary/GetProcAddress for using glfw.dll rather than compile-time CGO/GCC/LD linking -- since the latter cannot be made to work in 64-bit Windows sadly, not sure whether mingw64 or gcc or cgo is to blame. With LoadLibrary/GetProcAddress calling my custom 64-bit build of glfw.dll is working mighty fine. Clearly the issue here is with a call to the gl package, not glfw.
-
The gl package is indeed simply this one, unmodified. I experimented with a few LDFLAGS modifications such as -m64 -lmingw32 -Wl,/windows/opengl32.dll etc. but no difference, the original works just as fine as the modified ones as long as gl.Clear() is not called, so I reverted back to the original. Of course later on I'll move on to OpenGL 4.2.
-
Using Process Explorer, I can see my process is 64-bit and all loaded DLLs are 64-bit images too (including opengl32.dll and glfw.dll).
-
"could it be that the gl21 package could not obtain a valid address for the glClear() function exported by opengl32.dll?" -- unlikely: according to line 2926, my call to gl.Init() would fail if this were the case.
-
GPU driver issues? Even more unlikely. The very newest official nVidia Quadro 5010M driver 296.35 is installed. Also tried the "performance driver" but seems to be exactly the same driver anyway. Full OpenGL 4.2 support according to nVidia Control Panel (although opengl32.dll is dated 2009 -- anyway, plenty for 2.1 I'm currently targeting). Plus, the OpenGL shaders in "Geeks3D GPU Caps Viewer" and "Shader Toy Mark" run, as does the GLFW example program particles.exe -- all of them use glClear() as well.
-
Exact same issue happens when using gl42 instead of gl21, so that's not the cause either.
Do note how all other gl.SomeExportedFunc() calls do not crash in this example...
What to do, how to proceed?
I could live with this if this only happens with gl.Clear() and no other funcs ever -- I'm only ever rendering full-screen quads with custom content anyway -- but I'm fairly early in testing Win64 here (got a lot of gl42 code working just fine under Linux64, now about to "port" to Win64) and I fear that additional further calls later on will expose the same problem so I'm reporting this now. I will soon find out which other calls are affected by this.
答案1
得分: 1
你不能在没有CGO生成的存根的情况下调用C函数。
英文:
You cannot call C functions without the CGO generated stubs.
答案2
得分: 0
最新版本的Go、GLFW和Mingw-w64已经解决了这个问题。
英文:
No longer an issue with the newest releases of Go, GLFW and Mingw-w64.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论