首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >递归数据结构解组在Go Lang Protobuf中产生“无法解析无效线格式数据”的错误。

递归数据结构解组在Go Lang Protobuf中产生“无法解析无效线格式数据”的错误。
EN

Stack Overflow用户
提问于 2022-05-05 11:54:01
回答 2查看 4.4K关注 0票数 3

OS和protobuf版本

go1.18.1 linux/amd64 64,github.com/golang/protobuf v1.5.2

Introduction

我正在尝试使用递归的proto定义。

.proto文件

代码语言:javascript
运行
复制
message AsyncConsensus {
  int32 sender = 1;
  int32 receiver = 2;
  string unique_id = 3; // to specify the fall back block id to which the vote asyn is for
  int32 type = 4; // 1-propose, 2-vote, 3-timeout, 4-propose-async, 5-vote-async, 6-timeout-internal, 7-consensus-external-request, 8-consensus-external-response, 9-fallback-complete
  string note = 5;
  int32 v = 6 ; // view number
  int32 r = 7;// round number
  message Block {
    string id = 1;
    int32 v = 2 ; // view number
    int32 r = 3;// round number
    Block parent = 4;
    repeated int32 commands = 5;
    int32 level = 6; // for the fallback mode
  }
  Block blockHigh = 8;
  Block blockNew = 9;
  Block blockCommit = 10;
}

以下是我的元帅和元帅

代码语言:javascript
运行
复制
func (t *AsyncConsensus) Marshal(wire io.Writer) error {
    data, err := proto.Marshal(t)
    if err != nil {
        return err
    }
    lengthWritten := len(data)
    var b [8]byte
    bs := b[:8]
    binary.LittleEndian.PutUint64(bs, uint64(lengthWritten))
    _, err = wire.Write(bs)
    if err != nil {
        return err
    }
    _, err = wire.Write(data)
    if err != nil {
        return err
    }
    return nil
}

func (t *AsyncConsensus) Unmarshal(wire io.Reader) error {

    var b [8]byte
    bs := b[:8]
    _, err := io.ReadFull(wire, bs)
    if err != nil {
        return err
    }
    numBytes := binary.LittleEndian.Uint64(bs)
    data := make([]byte, numBytes)
    length, err := io.ReadFull(wire, data)
    if err != nil {
        return err
    }
    err = proto.Unmarshal(data[:length], t)
    if err != nil {
        return err
    }
    return nil
}

func (t *AsyncConsensus) New() Serializable {
    return new(AsyncConsensus)
}

我的预期结果

当通过TCP封送和发送到同一个进程时,它应该正确地解除封送并产生正确的数据结构。

产生的误差

误差"cannot parse invalid wire-format data"

附加信息

我尝试使用非递归的.proto定义,以前从未遇到过这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-07 12:15:01

这不是Protobuf的bug,而是marshalunmarshal原型结构的问题。

作为一个具体的指导方针,永远不要同时使用marshalunmarshal原型,因为它会导致种族条件。

在您提供的特定示例中,我看到了递归数据结构,因此,即使对每次调用marshalunmarshal使用单独的结构,父类中的指针也很可能导致共享指针。

使用深度复制技术移除任何依赖项,这样就不会运行到争用条件。

代码语言:javascript
运行
复制
func CloneMyStruct(orig *proto.AsyncConsensus_Block) (*proto.AsyncConsensus_Block, error) {
    origJSON, err := json.Marshal(orig)
    if err != nil {
        return nil, err
    }

    clone := proto.AsyncConsensus_Block{}
    if err = json.Unmarshal(origJSON, &clone); err != nil {
        return nil, err
    }

    return &clone, nil
}
票数 1
EN

Stack Overflow用户

发布于 2022-05-05 12:18:30

我能想到的最愚蠢的错误是,wire.Write(bs)没有写入io.ReadFull(wire, bs)读取的字节,所以我只需要确保它们的返回值在这两种情况下实际上都是8。

然后我不太了解金刚/原型机,但我想它应该能做到这一点。你不应该创建围棋代码然后喊出来吗?我不知道该怎么称呼它。

如果您认为这实际上是protobuf实现中的一个问题,那么有一些在线protobuf-decoders可以帮助您。但是他们有时不正确地解释流,这可能是递归模式的情况,所以您必须小心。但至少他们帮助我调试了不止一次dedis/protobuf包。

最后,您可以使用递归数据创建一个最小的示例,检查它是否有效,然后慢慢地添加字段,直到它破坏…。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72126727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档