Go:在同时读取文件和字符串时出现无效的内存地址或空指针解引用错误。

huangapple go评论75阅读模式
英文:

Go: Invalid memory address or nil pointer dereference when reading files and strings at same time

问题

我有以下函数waitForInput,它监听TCP输入,连接创建后,将其分配给客户端结构体,该结构体是该函数的一个输入参数。

func waitForInput(client *util.Client) {
	defer close(out)

	var dstFile = ""
	var fileBytes = make([]byte, 0)
	reader := bufio.NewReader(client.Connection)
	for {

		if client.SendingOperation == "command" {
			line, err := reader.ReadBytes('\n')
			myString := strings.TrimSpace(string(line))
			action, _, body := getAction(myString)

			if action == "send" {
				dstFile = body
				client.SetSendingOperation("file")
			}
            //做一些其他的事情

		} else {
			fmt.Printf("IN FILE %s %s \n", client.Username, client.SendingOperation)
			bytes, err := reader.ReadBytes('\n')
			if err == nil {
				fmt.Printf("ERROR:: ", err.Error())
			}

			fmt.Printf("The bytes: %s \n", bytes)
			fmt.Printf("fileBytes: %s \n", fileBytes)

			if err != nil {
				if err == io.EOF {
					writeBytesToFile(dstFile, fileBytes)
                    //先返回监听命令
					client.SetSendingOperation("command")
					fileBytes = make([]byte, 0)
				}
			}else {
				fileBytes = append(fileBytes, bytes...)
			}
		}
	}
}

该函数可以读取命令或文件,它们作为字节数组发送,并且如果是命令+文件,则会将它们附加在一起,例如messageBytes = append(commandBytes, fileBytes...)。当只发送命令而不是命令+文件时,它运行正常。但是当同时发送命令和文件时,我遇到了以下错误:panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x1007285b0]。奇怪的是,如果我注释掉这个if检查:if err == nil {fmt.Printf("ERROR:: ", err.Error())},代码会打印出fmt.Printf("The bytes: %s \n", bytes)的结果,所以我不知道发生了什么,我已经试了几天来修复它,所以有人知道该怎么做吗?或者有人知道如何同时从客户端传递连接中的字符串和文件读取命令的替代方法吗?

英文:

I have the following function waitForInput that listens for TCP input, after the connection has been created and that one has been assigned to the client struct which is one of the input params of that one.

func waitForInput(client *util.Client) {
	defer close(out)

	var dstFile = ""
	var fileBytes = make([]byte, 0)
	reader := bufio.NewReader(client.Connection)
	for {

		if client.SendingOperation == "command" {
			line, err := reader.ReadBytes('\n')
			myString := strings.TrimSpace(string(line))
			action, _, body := getAction(myString)

			if action == "send" {
				dstFile = body
				client.SetSendingOperation("file")
			}
            //Do some other stuff

		} else {
			fmt.Printf("IN FILE %s %s \n", client.Username, client.SendingOperation)
			bytes, err := reader.ReadBytes('\n')
			if err == nil {
				fmt.Printf("ERROR:: ", err.Error())
			}

			fmt.Printf("The bytes: %s \n", bytes)
			fmt.Printf("fileBytes: %s \n", fileBytes)

			if err != nil {
				if err == io.EOF {
					writeBytesToFile(dstFile, fileBytes)
                    //Go back to listen commands first
					client.SetSendingOperation("command")
					fileBytes = make([]byte, 0)
				}
			}else {
				fileBytes = append(fileBytes, bytes...)
			}
		}
	}
}

That function can read either commands or files, which are sent as byte arrays appended (if it's command + file) like messageBytes = append(commandBytes, fileBytes...). It works fine when sending only commands and not both, commands + files. But when sending commands and files I got the following error: panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x1007285b0]
, The weird thing is that if I comment that if check: if err == nil {fmt.Printf("ERROR:: ", err.Error())}, the code prints the bytes resulting from fmt.Printf("The bytes: %s \n", bytes), so I don't know whats going on, and I've been trying to fix it by days, so does anyone know what to do there, or does anyone know an alternative for reading commands as strings and files passed in a connection from a client to a server at the same time?

答案1

得分: 1

if err == nil {
    fmt.Printf("ERROR:: ", err.Error())
}

这段代码会导致panic: runtime error: invalid memory address or nil pointer dereference,因为在检查err == nil之后,你仍然访问了err.Error()。所以在这种情况下,nil.Error()会抛出错误。

我建议删除上面的代码块,并修改代码中更下面的错误处理部分。

fmt.Printf("IN FILE %s %s \n", client.Username, client.SendingOperation)
bytes, err := reader.ReadBytes('\n')

// 移除这部分
// if err == nil {
//     fmt.Printf("ERROR:: ", err.Error())
// }

fmt.Printf("The bytes: %s \n", bytes)
fmt.Printf("fileBytes: %s \n", fileBytes)

if err != nil {
    if err == io.EOF {
        writeBytesToFile(dstFile, fileBytes)
        // 返回到首先监听命令
        client.SetSendingOperation("command")
        fileBytes = make([]byte, 0)
    } else { // 添加这个 else 块
        fmt.Printf("ERROR:: ", err.Error())
    }
} else {
    fileBytes = append(fileBytes, bytes...)
}
英文:

>
> if err == nil {
> fmt.Printf("ERROR:: ", err.Error())
> }
>

This will definitely give panic: runtime error: invalid memory address or nil pointer dereference since you are accessing err.Error() after you have already checked err == nil. So in this case nil.Error() is throwing the error.

I would suggest removing the above code code block and modify the error handling further down the code.

fmt.Printf("IN FILE %s %s \n", client.Username, client.SendingOperation)
bytes, err := reader.ReadBytes('\n')

// REMOVE THIS
// if err == nil {
//     fmt.Printf("ERROR:: ", err.Error())
// }

fmt.Printf("The bytes: %s \n", bytes)
fmt.Printf("fileBytes: %s \n", fileBytes)

if err != nil {
    if err == io.EOF {
        writeBytesToFile(dstFile, fileBytes)
        //Go back to listen commands first
        client.SetSendingOperation("command")
        fileBytes = make([]byte, 0)
    } else { // ADD THIS ELSE BLOCK
        fmt.Printf("ERROR:: ", err.Error())
    }
} else {
    fileBytes = append(fileBytes, bytes...)
}

huangapple
  • 本文由 发表于 2022年4月22日 03:04:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/71959716.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定