Home > OS >  New to GO. Having invalid memory access related errors
New to GO. Having invalid memory access related errors

Time:05-25

extremely green in the world of GO - infact this is my first ever program in GO. I'm writing an algorithm that reverses a linked list, specifically from this leetcode. The code snippet below doesn't disclose my algorithm, only the main() function I'm using to test my implementation. After debugging, I found that I fail at the here arrow with the error message panic: runtime error: invalid memory address or nil pointer dereference.

type ListNode struct {
    Val int
    Next *ListNode
}
func main(){
    var list *ListNode
    head := list
    for i := 0; i <= 5; i   {
        var dummy *ListNode
        list.Val = i    <--------------------- here
        list.Next = dummy
        dummy = list
    }
    result := reverseList(head)

    for result != nil{
        fmt.Printf("%d\t", result.Val)
    }
}

I would really appreciate some discussion to this problem!

CodePudding user response:

The basic problem is that you're never allocating memory for your struct pointers. When you write:

var list *ListNode

You have created a pointer-to-ListNode type, but you haven't actually allocated any memory for it. So when you try to write...

list.Val = i

You get the "invalid memory address" error, because you're trying to dereference an undefined pointer. One way of allocating memory is to use the new() new builtin function:

var list *ListNode = new(ListNode)

You can also take the address of a struct, like this:

list := &ListNode{}

The above shows the correct syntax, but if you were to simply replace your existing var declaration with the above you would still have logic problems in your code: you don't want to allocate any memory until you add the first node to the list. That means we want to wait until we're inside the for loop to allocate memory.

With some minor changes to your code, we get:

package main

import "fmt"

type ListNode struct {
    Val  int
    Next *ListNode
}

func main() {
    var head, tail *ListNode

    for i := 0; i <= 5; i   {
        node := new(ListNode)
        node.Val = i

        if tail == nil {
            // This is the first node in the list, so just point head
            // and tail at the new node.
            tail = node
            head = tail
        } else {
            // There is at least one node in the list, so attach the new
            // node to the tail
            tail.Next = node
            tail = node
        }
    }

    result := head

    for result != nil {
        fmt.Printf("%d\t", result.Val)

        // Don't forget to increment to the next node!
        result = result.Next
    }
}

Running this code produces:

0       1       2       3       4       5

CodePudding user response:

You must allocate memory for the list nodes. As the list nodes are created, either update the Next field in the previous node or the list head if this is the first node.

var head *ListNode

// p is pointer to head or pointer to previous node's Next.  
// We start with p set as pointer to the head.
p := &head

for i := 0; i <= 5; i   {
    // Allocate a new ListNode with Val initialized.
    n := &ListNode{Val: i}

    // Update head or previous node'a Next field.
    *p = n

    // The next iteration of the loop should update
    // the Next field in the node that we just created.
    p = &n.Next
}

// Loop while list node is not nil.
for n := head; n != nil; n = n.Next {
    fmt.Println(n.Val)
}
    

https://go.dev/play/p/qUhza05kUFT

  •  Tags:  
  • go
  • Related