- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我在 Go 中有这个简单的 OpenGL 程序。
当我编译并运行它时,主游戏循环在因分段违规而崩溃之前经历了大约 9 次迭代。
rendering for the 0 time
rendering for the 1 time
rendering for the 2 time
rendering for the 3 time
rendering for the 4 time
rendering for the 5 time
rendering for the 6 time
SIGSEGV: segmentation violation
PC=0x7fdab95a0e29
signal arrived during cgo execution
runtime.cgocall(0x414f90, 0x7fdab9887e88)
/usr/lib/go/src/pkg/runtime/cgocall.c:149 +0x11b fp=0x7fdab9887e70
github.com/go-gl/gl._Cfunc_glClear(0xc200004100)
github.com/go-gl/gl/_obj/_cgo_defun.c:340 +0x31 fp=0x7fdab9887e88
github.com/go-gl/gl.Clear(0x4100)
/mnt/data/Dropbox/Coding/Go/src/github.com/go-gl/gl/gl.go:161 +0x25 fp=0x7fdab9887e98
main.draw()
/home/josh/Coding/Go/src/github.com/JoshWillik/Wander/wander.go:120 +0x25 fp=0x7fdab9887eb8
main.main()
/home/josh/Coding/Go/src/github.com/JoshWillik/Wander/wander.go:52 +0x300 fp=0x7fdab9887f48
runtime.main()
/usr/lib/go/src/pkg/runtime/proc.c:220 +0x11f fp=0x7fdab9887fa0
runtime.goexit()
/usr/lib/go/src/pkg/runtime/proc.c:1394 fp=0x7fdab9887fa8
goroutine 3 [syscall]:
runtime.goexit()
/usr/lib/go/src/pkg/runtime/proc.c:1394
rax 0x0
rbx 0x7fdab9887e88
rcx 0x7fdab9887e88
rdx 0x7fdab9887e20
rdi 0x4100
rsi 0xc210001900
rbp 0xc21002a000
rsp 0x7fdab2a4ddd8
r8 0xc210001120
r9 0x7fdab9887e20
r10 0x0
r11 0x286
r12 0x0
r13 0x7fdab9a74000
r14 0x0
r15 0x7fdab2a4e700
rip 0x7fdab95a0e29
rflags 0x10202
cs 0x33
fs 0x0
gs 0x0
如果我删除 shouldRender
函数中的基于时间的逻辑,它会在崩溃前进行大约 28-29 次迭代。
如果我在 draw
函数中删除对 gl.Clear()
的调用,它会在崩溃前持续到 90 年代。
如果我在 shouldRender
中删除对 fmt.Println()
的调用,游戏将按预期运行而不会崩溃。 (我已经测试了大约 2 或 3 分钟,所以将近 10,000 帧)
这让我怀疑对 fmt.Println()
的调用在某种程度上导致了分段违规。我误读了这些标志吗?如果不是,像 Println()
这样的核心函数怎么会这么不稳定?
package main
import (
f "fmt"
"github.com/go-gl/gl"
glfw "github.com/go-gl/glfw3"
"math"
"time"
)
var (
numRendered = 0
lastDraw = time.Now()
fps = 60
seconds = time.Now()
attr gl.AttribLocation
)
func main(){
if !glfw.Init(){
f.Println("Failed to init glfw")
panic("Cannot initialize glfw library")
}
defer glfw.Terminate()
//glfw.WindowHint(glfw.DepthBits, 16)
window, err := glfw.CreateWindow(300, 300, "Wander", nil, nil)
if err != nil{
panic(err)
}
window.SetFramebufferSizeCallback(reshape)
window.SetKeyCallback(key)
window.MakeContextCurrent()
glfw.SwapInterval(1)
width, height := window.GetFramebufferSize()
reshape(window, width, height)
if gl.Init() != 0 {
panic("Failed to init GL")
}
prog := setupProgram()
defer prog.Delete()
prog.Use()
attr = prog.GetAttribLocation("offset")
setup()
for !window.ShouldClose() {
if shouldRender(){
draw()
}
animate()
window.SwapBuffers()
glfw.PollEvents()
}
}
func setupProgram()(prog gl.Program){
vertexSource := `
#version 430 core
layout (location = 0) in vec4 offset;
const vec4 vertecies[3] = vec4[3](
vec4(0.25, 0.5, 0.5, 1.0),
vec4(-0.25, 0.5, 0.5, 1.0),
vec4(-0.25, -0.5, 0.5, 1.0)
);
void main(){
gl_Position = vertecies[gl_VertexID] + offset;
}`
fragmentSource := `
#version 430 core
out vec4 color;
void main(){
color = vec4(1.0, 0.0, 0.0, 0.0); // red, blue, green, ??
}`
vert, frag := gl.CreateShader(gl.VERTEX_SHADER), gl.CreateShader(gl.FRAGMENT_SHADER)
defer vert.Delete()
defer frag.Delete()
vert.Source(vertexSource)
frag.Source(fragmentSource)
vert.Compile()
frag.Compile()
prog = gl.CreateProgram()
prog.AttachShader(vert)
prog.AttachShader(frag)
prog.Link()
prog.Use()
f.Println(prog.GetInfoLog())
return
}
func key(window *glfw.Window, k glfw.Key, s int, action glfw.Action, mods glfw.ModifierKey) {
if action != glfw.Press {
return
}
switch glfw.Key(k){
case glfw.KeyEscape:
window.SetShouldClose(true);
default:
return
}
}
func reshape(window *glfw.Window, width, height int){
gl.Viewport(0, 0, width, height)
}
func draw(){
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.DrawArrays(gl.TRIANGLES, 0, 3)
}
func shouldRender() bool{
if int(time.Since(lastDraw) * time.Second) >= 1000/fps{
//f.Println("rendering for the ", numRendered, " time")
numRendered++
lastDraw = time.Now()
return true
}
return false;
}
func animate(){
now := float64(time.Since(seconds))
offset := [4]float32{
float32(math.Sin(now)),
float32(math.Cos(now)),
0.0,0.0}
attr.Attrib4fv(&offset)
red := gl.GLclampf(math.Sin(now) * 0.25 + 0.75)
blue := gl.GLclampf(math.Cos(now) * 0.25 + 0.75)
green := gl.GLclampf(time.Since(seconds))
_ = green;
gl.ClearColor(red, blue, 0.2, 0.0)
}
最佳答案
我在我的机器上运行了您的代码——在 64 位 Windows 上运行 MinGW-w64。虽然我的带有 println 的代码运行的时间比你的长得多(崩溃前超过 30k 次调用),但我观察到相同的行为。
堆栈跟踪报告了对 gl 函数的调用,这给了我一个暗示:错误可能与 OpenGL 上下文有关。
确实,如果你加上
import (
//...
"runtime"
//...
)
和线
runtime.LockOSThread()
到 main 函数的顶部,错误消失了(或者至少在线程锁定的情况下它在我的机器上运行了几分钟,显然我无法证明它永远不会崩溃)。
当 Goroutines 被阻止执行某些任务(如 IO)时,Go 运行时会偶尔拆分额外的线程以保持程序运行。
我怀疑发生的事情是,有时在调用 Println 时,Goroutine 在系统调用中被阻塞,因此运行时通过在不同线程上运行主 goroutine 来“帮助”您。由于 OpenGL 上下文绑定(bind)到一个线程,这会导致您的程序在 GL 调用时崩溃,因为您在错误的线程上调用。
将 runtime.LockOSThread() 添加到 main 的顶部会强制主 Goroutine 始终在同一线程上执行,从而使所有 GL 调用保持在正确的上下文中。
我应该补充一点,我简要浏览了 fmt 包的源代码,从我所看到的,我无法证明 goroutine/thread 废话肯定会发生;但是,根据我对 Go 运行时的了解以及 LockOSThread 似乎修复它的事实,我强烈怀疑情况就是如此。
无论哪种方式:当您使用依赖于将上下文绑定(bind)到单个线程的 C 库(例如 OpenGL 或 OpenAL)时,请确保始终使用 runtime.LockOSThread 将其运行的 Goroutine 锁定到一个线程。
更新:我在 the Go scheduler 上找到了这份文件,如果我没看错的话,它证实了我的怀疑。诸如打印之类的系统调用可以调用要生成的新线程,以允许调用 goroutine 在程序被 IO 阻塞时继续。
关于opengl - Golang fmt.Println() 导致游戏崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21010854/
在我们的项目中,我们决定在我们的项目中使用最新的 fmt 版本 (6.2.0) 并主要使用 printf 功能,因为我们在广泛使用 printf 的地方进行日志记录。 我使用 fmt 包中包含的 CM
JSTL 标签用来绑定数据源(.properties)文件,JSTL 标签用来从指定的资源文件中调用信息。 语法 JSP 标签的语法如下: 代码块 其中: basename:指定要
我有以下 JSTL: enumValue.reputation 给出“非常好”、“完美”等字符串,对于这种情况,我需要将其小写“非常好”、“完美”。怎么把它变成小写?
为什么是这样fmt::format_to(OutputIt, ...)而不是 fmt::print(OutputIt, ...) ?? 我目前正在熟悉 {fmt} , 一个/现代 C++ 格式库。 在
所以我目前正在开始使用 Rust,并且正在阅读我的 Rust By Example。 做练习,边玩边玩代码。 但在 RBE Display函数描述它将 Fmt::Display 描述为比 Fmt::D
我不确定如何命名这个问题,因为我是 Rust 新手,所以请随意提出修改建议。 我有两个结构。一个是 Job 结构,其中包含一些数字,例如作业需要多长时间等。另一个是 JobSequence,其中包含
我不确定如何命名这个问题,因为我是 Rust 新手,所以请随意提出修改建议。 我有两个结构。一个是 Job 结构,其中包含一些数字,例如作业需要多长时间等。另一个是 JobSequence,其中包含
关于Golang中的标准I\O,网上所有的教程,无一异常(exception)地讨论和使用bufio,我测试过,效果很好。 但我的问题是关于使用 fmt 包读取标准输入,这要么给我错误,要么陷入循环。
正如标题,我很难描述这个问题。所以我在下面展示了示例代码、输入和输出。 package main import ( "fmt" ) func main() { for i := 1;
我正在尝试在我的 JSP Web 应用程序上本地化货币,问题是当我要求语言环境时,我只得到语言代码(“en”)而不是完整的语言和国家代码(“en_US”)。问题是,当 setLocale 的值不包含语
我使用的是 MACOS Mojave 版本 10.14.3,需要使用 GNU 编译器而不是 clang。 我使用 brew install gcc 安装了 gcc 编译器.然后我使用 brew ins
我正在尝试编译一些代码,但出现了一个非常奇怪的错误: the trait core::fmt::Show is not implemented for the type core::fmt::Show
我是 Go 语言和编程的新手。 谁能解释错误的含义以及我该如何解决? 最佳答案 使用 fmt.Println 而不是 fmt.PrintLn。将字母 L 小写。 关于go - undefined :
package main import ( "fmt" ) func main() { fmt.Printf("%c, %x, %x", 'ᚵ', 'ᚵ', "ᚵ") } 输出: ᚵ,
每当我在 Windows cmd 上的 Go 中运行 fmt.Print("\033c") 时,它不会清除屏幕,而是在我执行 console 时打印 c。 log("\033c") 在 javascr
我正在使用字典进行一些测试,为此,我以一种格式从数据库中打印出我想要的 Float64 值,以便将它们复制并粘贴到我的测试结构数组中,但是当我的测试失败时,我注意到这些值不同,但仅相差 0.00000
我目前有一个项目是这样组织的: ~/code/go /bin /pkg /src /proj/main.go
我目前正在做一个 spring 项目,我不得不在我的 JSP 中使用 fmt 标签。事实上 fmt 标签对我来说工作正常,它从 messages.properties 读取正确的值文件。 例如: 在
我想知道{fmt}库是否只允许修改包含多个位置参数的字符串中的一个位置参数? 这是我的测试不起作用,{fmt}文档未显示解决方案 std::string text = "{name} is {nb}
Closed. This question is not reproducible or was caused by typos。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-to
我是一名优秀的程序员,十分优秀!