2017-10-31 28 views
-3

EDIT : 프로그램을 다시 작성했는데 성공했습니다. 이 질문은 더 이상 사용되지 않습니다.예기치 않은 nil pointer golang (SIGSEGV가있는 패닉)

나는 os.Argument에서 입력을 읽고 토큰 화하고 실행합니다 (사소한 언어 렉서입니다). 입력은 안녕하세요 세계 문입니다 :

print 'Hello, World!' 

프로그램을 실행, 내가 얻을 :

panic: runtime error: invalid memory address or nil pointer dereference 
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x496b0c] 

goroutine 1 [running]: 
main.(*Command).Execute(0x0) 
    /home/vikram/Projects/golang/src/github.com/vikramdurai/macaque/main.go:23 +0x2c 
main.main() 
    /home/vikram/Projects/golang/src/github.com/vikramdurai/macaque/main.go:69 +0x15a 

프로그램 :

var tokStack = make([]*Command, 1) 

type Command struct { 
    Name  string 
    Arguments []interface{} 
} 

func (c *Command) AddArgument(arg interface{}) { 
    c.Arguments = append(c.Arguments, arg) 
} 

func (c *Command) Execute() { 
    switch c.Name { 
    case "print": 
     for _, v := range c.Arguments { 
      fmt.Printf("%v", v) 
     } 
     fmt.Print("\n") 
    } 
} 

func token(line_num int, tok string) { 
    tokens := strings.Split(tok, " ") 
    switch tokens[0] { 
    case "print": 
     command := &Command{Name: "print"} 
     var text string 
     if tokens[1] == "'" { 
      if tokens[len(tokens)-1] == "'" { 
       text = strings.Join(tokens[1:len(tokens)-2], " ") 
       command.AddArgument(text) 
      } else { 
       fail(errors.New(fmt.Sprintf("on line %v: string unclosed", line_num))) 
      } 
     } 
     tokStack = append(tokStack, command) 
    } 
} 

func fail(reason error) { 
    fmt.Errorf("macaque: %v\n", reason) 
    os.Exit(1) 
} 

func main() { 
    progname := os.Args[1] 
    if progname == "" { 
     fail(errors.New("argument not supplied")) 
    } 
    program, err := ioutil.ReadFile(progname) 
    if err != nil { 
     fail(err) 
    } 
    new_program := strings.Split(string(program), "\n") 
    for num, line := range new_program { 
     token(num, line) 
    } 
    for _, v := range tokStack { 
     v.Execute() 
    } 
    fmt.Printf("Total amount of tokens found: %v\n", tokStack) 
} 

사람이 왜 프로그램 패닉을 설명 할 수 있습니까? 포인터를 잘못 사용하고 있습니까?

미리 감사드립니다.

답변

1

tokStack 슬라이스를 만들 때 하나의 요소가 포함되도록 make(..., 1)을 사용하면됩니다. 025 포인터 유형 인 *Command 유형의 값은 0입니다. 그런 다음 Execute을 main의 nil 값으로 호출합니다.

슬라이스를 처음부터 아무것도 포함하지 않아도됩니다.

+0

패닉이 사라졌지만 프로그램에서 '발견 된 토큰 총계 : [0xc42008c120]' –

+0

@VikramDurai : 어떻게 될 것으로 예상됩니까? 한 줄을 제공하고 하나의'* Command' 조각을 만들었습니다. 너는 무엇을 놓치고 있니? – JimB

+0

내가 입력 한 내용은'print 'Hello World''입니다. 그리고이 프로그램은'Hello World \ n 총 발견 된 토큰의 양 : [print]'을 인쇄하기로되어있었습니다. 어쩌면 프로그램을 잘못 작성했을 수도 있습니다. –