c++ - 使用 protobuf 序列化数据的问题 - 在发布版本中生成了无效的二进制流(消息中的 1 个额外字节)
问题描述
我在 Windows 上使用带有 protobuf 3.10.0 的 Visual Studio 2017 的 C++ 中的 protobuf 遇到了一个奇怪的问题。
由于我还无法找出根本原因,也无法创建一个我可以分享的有用的最小示例代码示例,所以我试图尽可能好地解释这个问题。如果有人遇到相同或类似的问题,我的目标是获得一些输入,以了解如何调试问题。寻找任何有用的想法。
我已经为一个复杂的现有项目添加了用于序列化的协议缓冲区。到目前为止,这工作得很好。
但是最近我们开始看到一个问题,即序列化的流无法被相同的可执行文件再次反序列化。
问题:我们无法反序列化我们之前序列化的 protbuf 流(并不总是发生,但对于某些数据似乎是可重复的)。
分析序列化的 protobuf 原始流,它看起来在 protobuf 流中存在单个额外字节(通常0xCD
......),通常在单个字段的二进制表示中(在字段的长度和内容之间)。消息和字段的大小似乎是“正确的”(如果不存在恶意的额外字节)。
有一些线索似乎表明这是 VS2017 C++ 编译器优化的问题:
我们的构建服务器和大多数开发人员的 PC 运行 VS 2017 Vers。15.9.x。该问题可能出现在这些机器上构建的可执行文件中。当移动到具有 15.9.x 版本的新构建服务器时,它开始发生。
我有一台仍在 VS 2017 V.15.7.6上的 PC ;到目前为止,我们无法揭露该 PC 上构建的可执行文件的问题。
到目前为止,我们无法在任何调试版本上重现该问题。
我们之前在 protobuf 3.5.1 中遇到了相同或非常相似的问题(在序列化过程中,protobuf 抛出了一个 FatalException,表明预测的大小与流长度不匹配),也只存在于 VS2017 工具链版本的发布版本中问题,但是当我们切换到 protobuf 3.10.0 时,它暂时消失了。在 3.10.0 中,导致 FatalException 的检查似乎已被删除(我知道解析器/序列化程序在 3.10.0 中已更改)并且不再抛出 FatalException。这个问题也发生在较少的情况下。
此外,我们在消息中拥有的数据似乎在问题是否发生方面发挥了作用。
调试问题或将问题隔离为我可以真正查明某个优化或一段代码作为罪魁祸首的形式有点困难。到目前为止,试图在应该暴露问题的“最小工作样本”中重新创建问题失败了。我也看不到 protobuf 代码中有任何可疑之处。我的想法已经不多了,想知道是否有人面临类似的问题,或者对我可以采取的下一步措施有什么想法。是的,我搜索了互联网,但到目前为止我没有发现任何关于这个问题的信息。如果我可以发布有关该问题的更多信息(除了:源代码...),请告诉我。
信息:
协议缓冲区是从源代码构建的,使用 cmake 和用于构建主项目的相同 VS2017 工具链。
它静态链接到主应用程序。
protobuf 库和主项目的外部 dll (/MD) 中的 C++ 运行时。
用于生成代码的 protobuf 编译器 (protoc) 来自与链接到项目的 protobuf 库和编译的头文件相同的构建。
我们不会同时访问要从其他线程序列化的 protobuf 消息对象。
解决方案
推荐阅读
- php - 获取 Woocommerce 中每种产品今天的总订单数
- split - Typoscript Split Wrap 仅在不为空时拆分?
- php - Laravel:一对多关系问题
- python - 如何使用 python 从网页中检索信息并使代码吐出
- string - 如何检测 mql4 中的字符串结束位置?
- javascript - 在任意深度的嵌套数组中查找值
- c - PostgreSQL:我的 C (libpq) 程序如何检测哪个表约束触发了错误?
- ruby-on-rails - 如何在 Rspec 中测试环境变量的存在
- woocommerce - 如何为每个项目、每个用户和每个日期设置 WooCommerce 订单的最大限制
- c# - CanFreeze 返回 false,因为 Freezable 上的 DependencyProperty 的值是一个表达式