当前位置: 首页 > 知识库问答 >
问题:

grpc:使用其中一个会导致无效内存地址或零指针解引用

段弘和
2023-03-14

我正在尝试使用Go将原型3结构发送到gRPC服务器。该结构具有oneof类型,我似乎可以很好地填充它。当将消息发送到我的gRPC客户端时,我对无效内存地址或nil指针引用感到恐慌。

我有原始定义(完整文件在https://github.com/MovingGauteng/geofancy-rs/blob/master/proto/geofancy.proto:

# proto3

message Document {
  string collection = 1;
  string id = 2;
  oneof geo {
    Point point = 4;
    LineString line = 5;
    Bounds bounds = 6;
    string geojson = 7;
  }
}

message Point { Coordinate coord = 1; }

message Coordinate {
  double lat = 1;
  double lng = 2;
}

围棋代码是:

// create a coordinate
coord := geofancy.Coordinate{
  Lat: 10.2,
  Lng: -15.3,
}
// add coordinate to a point
point := geofancy.Point{
  Coord: &coord,
}

// these statements print valid data
log.Printf("Coord: %v", coord)
log.Printf("Point: %v", point)

// create document, add point to the oneof field
document := geofancy.Document{
  Collection:   "some-collection",
  Id:           "some-id",
  Geo:          &point,
}

// this prints the document correctly
log.Printf("Document: %v", document)

// connect to client
var opts []grpc.DialOption
opts = append(opts, grpc.WithInsecure())
var err error
conn, err := grpc.Dial("my-server:port", opts...)
if err != nil {
    log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := geofancy.NewGeofancyServiceClient(conn)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// this panics each time
res, err := client.SetDocument(ctx, &document)

堆栈跟踪如下所示:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x10 pc=0x54d731]

goroutine 1 [running]:
my-project/vendor/github.com/golang/protobuf/proto.makeOneOfMarshaler.func1(0xc000068ce0, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/github.com/golang/protobuf/proto/table_marshal.go:2373 +0x131
my-project/vendor/github.com/golang/protobuf/proto.(*marshalInfo).size(0xc0003021c0, 0xc000068cc0, 0xf9ef40)
        D:/projects/golang/src/my-project/vendor/github.com/golang/protobuf/proto/table_marshal.go:183 +0xa8
my-project/vendor/github.com/golang/protobuf/proto.(*InternalMessageInfo).Size(0xf9ef40, 0xae7fa0, 0xc000068cc0, 0x30448c0)
        D:/projects/golang/src/my-project/vendor/github.com/golang/protobuf/proto/table_marshal.go:125 +0x6e
my-project/vendor/my-protos.(*Document).XXX_Size(0xc000068cc0, 0xae7fa0)
        D:/projects/golang/src/my-project/vendor/my-protos/geofancy.pb.go:197 +0x4a
my-project/vendor/github.com/golang/protobuf/proto.(*Buffer).Marshal(0xc0002de698, 0xae7fa0, 0xc000068cc0, 0xc0000363f0, 0xc000068cc0)
        D:/projects/golang/src/my-project/vendor/github.com/golang/protobuf/proto/table_marshal.go:2740 +0x8c
my-project/vendor/google.golang.org/grpc/encoding/proto.marshal(0xa0c520, 0xc000068cc0, 0xc0002de690, 0x0, 0x0, 0xc000006000, 0x99a900, 0x1)        
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/encoding/proto/proto.go:59 +0xe9
my-project/vendor/google.golang.org/grpc/encoding/proto.codec.Marshal(0xa0c520, 0xc000068cc0, 0x0, 0x2030000, 0x2030000, 0x30000, 0x20)
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/encoding/proto/proto.go:74 +0xb4
my-project/vendor/google.golang.org/grpc.encode(0x3080168, 0xfbc400, 0xa0c520, 0xc000068cc0, 0xc000310020, 0xc000362000, 0x11d0008, 0x0, 0x0)       
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/rpc_util.go:543 +0x59
my-project/vendor/google.golang.org/grpc.prepareMsg(0xa0c520, 0xc000068cc0, 0x3080168, 0xfbc400, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/stream.go:1501 +0x8c
my-project/vendor/google.golang.org/grpc.(*clientStream).SendMsg(0xc00032e000, 0xa0c520, 0xc000068cc0, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/stream.go:681 +0x157
my-project/vendor/google.golang.org/grpc.invoke(0xaed320, 0xc000068f60, 0xa42207, 0x25, 0xa0c520, 0xc000068cc0, 0x9e3000, 0xc00003c840, 0xc000065180, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/call.go:70 +0xee
my-project/vendor/google.golang.org/grpc.(*ClientConn).Invoke(0xc000065180, 0xaed320, 0xc000068f60, 0xa42207, 0x25, 0xa0c520, 0xc000068cc0, 0x9e3000, 0xc00003c840, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/google.golang.org/grpc/call.go:37 +0x1bb
my-project/vendor/my-protos.(*geofancyServiceClient).SetDocument(0xc000006030, 0xaed320, 0xc000068f60, 0xc000068cc0, 0x0, 0x0, 0x0, 0xc000065180, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/my-protos/geofancy.pb.go:925 +0xd9
main.sendMyMessage(0xc0002e4000, 0x77359400)
        D:/projects/golang/src/my-project/main.go:89 +0x685
main.main()
        D:/projects/golang/src/my-project/main.go:117 +0xf4

共有1个答案

陆城
2023-03-14

我很惊讶你的代码正在编译。我非常感兴趣,以至于我在我的环境中生成了Go代码来理解它。

“geofunce.Document”结构无法接收点作为属性Geo的值,因为它需要一个通用的“Document Geo”(可以是Document_点、Document_线字符串等)

自动生成的代码有一个界面,您可以在这种情况下使用。

    // add coordinate to a point
    point := geofancy.Document_Point{
        Point: &geofancy.Point{
            Coord: &coord,
        },
    }

现在,变量point是一个结构,它实现了Geo可以接受的接口。

document := geofancy.Document{
  Collection:   "some-collection",
  Id:           "some-id",
  Geo:          &point,
}

我无法使用您的示例进行编译,因为它收到了错误:

 cannot use &point (type **geofancy.Point) as type geofancy.isDocument_Geo in field value:
    **geofancy.Point does not implement geofancy.isDocument_Geo (missing geofancy.isDocument_Geo method)```

 类似资料:
  • 调用原子。结构字段上的AddInt64会恐慌,但当我们重新排列字段顺序时不会;为什么? 使用此类型: 并调用

  • 我是gccgo新手,我需要编译/运行以下代码的帮助(这在“标准”go编译器中可以正常工作(抱歉,我不知道正确的名称)): 我的gcc: 我的第一个文件: 我的第二个文件: 我的编译错误: 我做错了什么?

  • 我正在尝试实现简单的grpc服务器和客户端模型,只使用服务器端流的方法。我正在参考Official repo中的路线指南示例。尝试运行时,我从服务器端收到此错误 这是客户端的 服务器去 一些原型文件 我正在研究堆栈溢出中关于零指针错误的几个问题,我发现这段代码是罪魁祸首 我不知道如何解决这个问题,我怀疑我实施它的方式是错误的。任何帮助都将是巨大的。谢谢

  • 我收到一个无效内存地址的运行时错误。 channel.go看起来像这样: 第36行怎么可能导致这种情况?m是否有可能为零?如果是,如何? 注意:哈希定义为字符串

  • 我正在尝试使用带有自定义分隔符的Go html/模板。 但是,我可以解析并执行我的“index.html”文件,每当我试图更改模板分隔符时,我都会遇到以下错误: 这是我的代码: 如果我尝试以下任何一种: 或: 一切正常。我甚至试图捕捉ParseFiles错误。但仍然没有运气: 我看不出我做错了什么。如果你们中的任何人能在这个问题上帮助我,我将不胜感激。 更新1: 这就是恐慌:

  • 我是新手,试图制作一个简单的网络爬虫。我一直收到“恐慌:运行时错误:无效的内存地址或零指针取消引用”,不知道如何解决这个问题。我有一个“AdvancedFetcher”函数和一个“basicFetcher”函数,我在其中任何一个下都收到相同的错误。这个答案建议检查每个错误(我想我有),但我仍然收到错误。谢谢! 编辑#1: