0

As an exercise I created a small HTTP server that generates random game mechanics, similar to this one. I wrote it on a Windows 7 (32-bit) system and it works flawlessly. However, when I run it on my home machine, Windows 7 (64-bit), it always fails with the same message: exit status -1073741819. I haven't managed to find anything on the web which references that status code, so I don't know how important it is.

Here's code for the server, with redundancy abridged:

package main

import (
    "fmt"
    "math/rand"
    "time"
    "net/http"
    "html/template"
)

// Info about a game mechanic
type MechanicInfo struct { Name, Desc string }

// Print a mechanic as a string
func (m MechanicInfo) String() string {
    return fmt.Sprintf("%s: %s", m.Name, m.Desc)
}

// A possible game mechanic
var (
    UnkillableObjects = &MechanicInfo{"Avoiding Unkillable Objects",
                                      "There are objects that the player cannot touch. These are different from normal enemies because they cannot be destroyed or moved."}
    //...
    Race              = &MechanicInfo{"Race",
                                      "The player must reach a place before the opponent does. Like \"Timed\" except the enemy as a \"timer\" can be slowed down by the player's actions, or there may be multiple enemies being raced against."}
)

// Slice containing all game mechanics
var GameMechanics []*MechanicInfo

// Pseudorandom number generator
var prng *rand.Rand

// Get a random mechanic
func RandMechanic() *MechanicInfo {
    i := prng.Intn(len(GameMechanics))
    return GameMechanics[i]
}


// Initialize the package
func init() {
    prng = rand.New(rand.NewSource(time.Now().Unix()))

    GameMechanics = make([]*MechanicInfo, 34)
    GameMechanics[0] = UnkillableObjects
    //...
    GameMechanics[33] = Race
}

// serving

var index = template.Must(template.ParseFiles(
    "templates/_base.html",
    "templates/index.html",
))

func randMechHandler(w http.ResponseWriter, req *http.Request) {
    mechanics := [3]*MechanicInfo{RandMechanic(), RandMechanic(), RandMechanic()}
    if err := index.Execute(w, mechanics); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {
    http.HandleFunc("/", randMechHandler)
    if err := http.ListenAndServe(":80", nil); err != nil {
        panic(err)
    }
}

In addition, the unabridged code, the _base.html template, and the index.html template.

What could be causing this issue? Is there a process for debugging a cryptic exit status like this?

4

1 に答える 1

1

実行すると、次の2つのエラーが発生しました。

template: content:6: nil pointer evaluating *main.MechanicInfo.Name
http: multiple response.WriteHeader calls

前者は Web ブラウザーにあり、後者はサーバーを起動したコンソール ウィンドウにありました。

nil ポインターの問題は、要約されたプログラムが GameMechanics[1:32] を nil に設定したままにしておくためです。

2 番目のエラーは興味深いものです。プログラム内で http.ResponseWriter のメソッドが呼び出される唯一の場所は index.Execute 内です。これはコードではありません。つまり、html/template で何か問題が発生している可能性があります。Go 1.0.2 でこれをテストしています。

index.html の先頭に _base.html を配置し、index を次のように変更しました。

var index = template.Must(template.ParseFiles("templates/index.html"))

http.WriteHeaders 警告はなくなりました。

本当の答えではありませんが、探求できる方向性です。

おまけとして、プログラムを書くためのより多くの「方法」があります。PRNG の使用を簡略化し (いくつかを並列に実行する場合を除き、インスタンス化する必要はありません)、構造初期化子を簡略化したことに注意してください。

package main

import (
    "fmt"
    "html/template"
    "math/rand"
    "net/http"
)

// Info about a game mechanic
type MechanicInfo struct{ Name, Desc string }

// Print a mechanic as a string
func (m MechanicInfo) String() string {
    return fmt.Sprintf("%s: %s", m.Name, m.Desc)
}

// The game mechanics
var GameMechanics = [...]*MechanicInfo{
    {"Avoiding Unkillable Objects",
        "There are objects that the player cannot touch. These are different from normal enemies because they cannot be destroyed or moved."},
    {"Race",
        "The player must reach a place before the opponent does. Like \"Timed\" except the enemy as a \"timer\" can be slowed down by the player's actions, or there may be multiple enemies being raced against."},
}

// Get a random mechanic
func RandMechanic() *MechanicInfo {
    i := rand.Intn(len(GameMechanics))
    return GameMechanics[i]
}

var index = template.Must(template.ParseFiles("templates/index.html"))

func randMechHandler(w http.ResponseWriter, req *http.Request) {
    mechanics := [3]*MechanicInfo{RandMechanic(), RandMechanic(), RandMechanic()}
    if err := index.Execute(w, mechanics); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func main() {
    http.HandleFunc("/", randMechHandler)
    if err := http.ListenAndServe(":80", nil); err != nil {
        panic(err)
    }
}
于 2012-08-28T15:36:23.523 に答える