2015-02-23 8 views
5

Aufruf von atomic.AddInt64 auf Feld eines Struct Panics invalid memory address or nil pointer dereference, aber nicht, wenn wir Felder Reihenfolge neu ordnen; Warum?atomic.AddInt64 Verursacht ungültige Speicheradresse oder Nullzeiger-Dereferenz

Mit dieser Art:

type CountHandler struct { 
    c  *RequestContext 
    count int64 
} 

Und ruft atomic.AddInt64(&countHandler.count, 1) (Feld c ist gleich Null an dieser Stelle) gerät in Panik. Aber nicht, wenn wir es umschreiben als:

type CountHandler struct { 
    count int64 
    c  *RequestContext 
} 

Fehler verschwindet.

Ich denke, es sollte so sein, denn Go hält Daten im Speicher in einer sequentiellen Weise und erreicht einen nil Wert bricht diese Sequenz (von Bytes); Doch ich frage mich, warum das so ist, denn ein Zeiger sollte eine feste Größe nil oder einen anderen Wert haben.

Dies ist Go x86 1.4.2 auf Windows & vollständige Fehlermeldung lautet:

2015/02/23 12:56:44 http: panic serving [::1]:51886: runtime error: invalid memory address or nil pointer dereference 
goroutine 5 [running]: 
net/http.func·011() 
     c:/go/src/net/http/server.go:1130 +0xa8 
sync/atomic.AddUint64(0x731144, 0x1, 0x0, 0x0, 0x263168) 
     c:/go/src/sync/atomic/asm_386.s:118 +0xc 
main.(*CountHandler).ServeHTTP(0x731140, 0x263180, 0x122f6380, 0x122f62a0) 
     C:/Workshop/Devox/Workshop-Go/src/geoho/web/app/app.go:62 +0x42 
github.com/julienschmidt/httprouter.func·001(0x263180, 0x122f6380, 0x122f62a0, 0x0, 0x0, 0x0) 
     C:/Workshop/Devox/Workshop-Go/src/github.com/julienschmidt/httprouter/router.go:232 +0x4c 
github.com/julienschmidt/httprouter.(*Router).ServeHTTP(0x122d5d20, 0x263180, 0x122f6380, 0x122f62a0) 
     C:/Workshop/Devox/Workshop-Go/src/github.com/julienschmidt/httprouter/router.go:298 +0x141 
net/http.serverHandler.ServeHTTP(0x122d2280, 0x263180, 0x122f6380, 0x122f62a0) 
     c:/go/src/net/http/server.go:1703 +0x145 
net/http.(*conn).serve(0x122e01e0) 
     c:/go/src/net/http/server.go:1204 +0x9d8 
created by net/http.(*Server).Serve 
     c:/go/src/net/http/server.go:1751 +0x2ce 

ganze Quellcode ist (dieser Code ist falsch, ich war nur alice über das Studium):

package main 

import (
    "fmt" 
    "github.com/julienschmidt/httprouter" 
    "github.com/justinas/alice" 
    "net/http" 

    "os" 
    "sync/atomic" 
) 

// play with alice 
func main() { 
    c1 := alice.New(Counter, Texter).Then(nil) 

    router := httprouter.New() 
    router.Handler("GET", "/", c1) 
    router.GET("/kill", kill) 

    http.ListenAndServe(":27007", router) 
} 

func kill(rw http.ResponseWriter, rq *http.Request, pl httprouter.Params) { 
    os.Exit(0) 
} 

var ch CountHandler 

// constructors: 

func Counter(h http.Handler) http.Handler { 
    return &ch 
} 

func Texter(h http.Handler) http.Handler { 
    var t TextHandler 
    switch x := h.(type) { 
    case *CountHandler: 
     t.c = x.c 
     t.text = fmt.Sprintf("called so far %d", atomic.LoadInt64(&x.count)) 
    } 
    return &t 
} 

// handlers: 

type RequestContext struct { 
    val int 
} 

type CountHandler struct { 
    c  *RequestContext 
    count int64 
} 

func (c *CountHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { 
    atomic.AddInt64(&c.count, 1) 
} 

type TextHandler struct { 
    c *RequestContext 
    text string 
} 

func (t *TextHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { 
    rw.Write([]byte(t.text)) 
} 
+0

Scheint wie ein Fehler für mich. Ich nahm Ihren Code und unter Linux läuft es gut. Gleiches auf dem Spielplatz. sehen Sie dies: http://play.golang.org/p/fDFaZPi3nf führt dieser genaue Code-Absturz auf Ihrem Windows-Rechner? –

+0

Ja, es sollte funktionieren. Bitte poste mehr Code, z.B. wie Sie Ihre 'countHandler'-Variable erstellen. Bitte zielen Sie auf [MCVE] (http://stackoverflow.com/help/mcve). – icza

+0

Danke; Ich habe den Code hinzugefügt. –

Antwort

11

Der Fehler wird im ersten Fall verursacht, wenn das atomar aktualisierte Feld nicht richtig aligned ist.

Auf beide ARM und x86-32, ist es in der Verantwortung des Anrufers für 64-Bit-Ausrichtung von 64-Bit-Worten atomar zugegriffen zu arrangieren. Es kann davon ausgegangen werden, dass das erste Wort in einer globalen Variablen oder in einer zugewiesenen Struktur oder Scheibe 64-Bit-ausgerichtet ist.

+0

Ooh, schöner Fang, ich habe den x86 Teil verpasst! –

Verwandte Themen