2

我今天对我的一个相当大的项目进行了一些更改,现在我遇到了一些奇怪的行为。因为我是个傻瓜,我无法回头弄清楚我做了什么。

但是我的问题的主旨是我应该如何理解打印的堆栈跟踪中的负行号。下面-1218是我的意思。

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x1 pc=0x80501f2]

goroutine 1 [running]:
server.init()              //     vv-------------RIGHT HERE
    /home/.../debugComponent.go:-1218 +0x282
_/home/.../possessions.init()
    /home/.../possessions.go:29 +0x42
_/home/.../pageWrap.init()
    /home/.../pageWrap.go:112 +0x47

main.init()
    /home/.../main.go:0 +0x3c

goroutine 2 [syscall]:

goroutine 3 [runnable]:

关联debugComponent.go文件现在非常不重要,所以我将其删除以查看会发生什么,文件名只是被替换为不同的文件名和不同的负数。

在开发这个应用程序时,我不得不发现很多错误,但这个让我很难过。


如果它有帮助,那么还有main.go几个包在玩。上面列出的三个文件都是不同的包,这似乎是在导入期间发生的。


我希望你已经读到这里,因为这是最奇怪的部分。如果我将此声明添加到main.go,错误就会消失!

var test = func() int { return 1 }() // Everything is fine now!

很混乱!如果我这样做,它不会解决它var test = "foobar"。它必须是被调用的func.


任何见解都值得赞赏,但主要是我对-1218跟踪中的内容感到好奇。


更新

我试图把它归结为一个重现问题的小例子。处理完之后,我恢复到原来的代码,并重新启动了机器。

我第一次尝试构建和运行时,堆栈跟踪顶部添加了两个新条目。但也只是第一次。

goroutine 1 [syscall]:
syscall.Syscall()
    /usr/local/go/src/pkg/syscall/asm_linux_386.s:14 +0x5
syscall.Mkdir(0x83a2f18, 0x2, 0x2, 0x806255e, 0x83a2f1c, ...)
    /usr/local/go/src/pkg/syscall/zerrors_linux_386.go:2225 +0x80
server.init()

所以这符合我关于解释堆栈跟踪的主要问题。仍然存在,但现在-1218有这些。

有这个asm_linux_386.s在线14

MOVL    4(SP), AX       // syscall entry

我也找到了zerrors_linux_386.go,但是没有行2225。该文件在该行之前很久就停止了。

4

2 回答 2

2

它已被报告并接受为Issue 5243

于 2013-07-10T09:51:37.897 回答
0

程序执行

一个没有导入的包通过为其所有包级变量分配初始值,然后调用任何具有名称和签名的包级函数来初始化

func init()

在其来源中定义。具有名称的包范围或文件范围标识符init只能声明为具有此签名的函数。即使在一个源文件中,也可以定义多个这样的函数;它们以未指定的顺序执行。

在一个包中,包级变量被初始化,并根据引用顺序确定常量值:如果A依赖于的初始化器BA将在之后设置B。依赖性分析不依赖于正在初始化的项目的实际值,只依赖于它们在源中的外观。A取决于B的 值是否A包含对 的提及B、包含初始化器提及的值B或提及的函数B,递归。如果这样的依赖形成一个循环,那就是错误的。如果两个项目不相互依赖,它们将按照它们在源中出现的顺序进行初始化,可能在多个文件中,如呈现给编译器的那样。由于依赖关系分析是针对每个包进行的,因此如果A的初始化程序调用在另一个包中定义的函数引用B.

init不能从程序中的任何地方引用函数。特别是,init不能显式调用,也不能将指针 init分配给函数变量。

如果包有导入,则在初始化包本身之前初始化导入的包。如果多个包导入一个包 PP只会初始化一次。

包的导入,通过构造,保证了初始化中不会有循环依赖。

一个完整的程序是通过将一个单独的、未导入的包(称为main包)与它导入的所有包链接起来的,传递性的。包main必须具有包名main并声明一个main不带参数且不返回值的函数。

func main() { … }

程序执行从初始化main包开始,然后调用函数main。当函数main返回时,程序退出。它不会等待其他(非main)goroutine 完成。

包初始化——变量初始化和 init函数调用——发生在一个 goroutine 中,顺序地,一次一个包。一个init函数可能会启动其他 goroutine,这些 goroutine 可以与初始化代码同时运行。然而,初始化总是对函数进行排序:在前一个函数返回之前,init它不会开始下一个函数。init

当您的程序开始执行时,它会初始化包变量并执行init函数。添加包变量将改变初始化。看起来初始化在debugComponent.goserver.init(). 负行号可能是一个错误。

没有源代码,很难说更多。

于 2013-05-31T01:44:51.957 回答