c++ - Protobuf 对象在传递给动态库时被损坏
问题描述
我正在将我的库与一些深度学习框架集成在一起,但遇到了一些内存问题。我怀疑 protobuf 是这里的问题,但我想征求你们的意见和一些帮助,因为我已经花了太多时间在这上面。简而言之,该框架在 ONNX 格式的深度学习模型上运行。它将它们读入内存中的onnx::ModelProto
对象。然后将这些对象传递给我的库,在那里它们被转换(和优化)为我的自定义表示并返回到框架。是从https://github.com/onnx/onnx/blob/master/onnx/onnx.protoonnx::ModelProto
生成的 C++ 类- 一个常规的 protobuf 消息。protoc
当ModelProto
到达我的图书馆时会出现问题。的主要成员ModelProto
是图,它是一个指针:onnx::GraphProto* onnx::ModelProto::graph_
. 当对象被传递到我的库时,图形指针被设置为一些不同的地址,这不是正确的GraphProto
对象位置:
framework:
model_proto: 0x2ccb450
graph address: 0x2cc1d20
---
mylib:
model_proto: 0x2ccb450
graph address: 0x7fb6529c2560
烦人的事情是它只发生在发布版本中。当我在调试中编译两者时 - 它可以正常工作。
此外,在出现此错误之前,我ModelProto
使用std::stringstream
- 我首先将框架中的模型序列化为字符串,从中创建一个流并在我的库中反序列化。反序列化完成后,图表也被破坏了,这太糟糕了,以至于我的代码中进一步出现了段错误。
这与框架和我的库都与它们自己的 protobuf 副本静态链接这一事实有关吗?Protobuf 作为依赖项添加,并与框架和我的库一起编译。我确保我使用相同的版本(目前是 3.11)。我也使用相同的 ONNX 版本(1.6)。
以下是依赖项和工作流程的外观:
解决方案
由于 C++ 中没有标准的 ABI,因此在单独构建的库之间传递对象的门槛非常高。
使用 protobuf 的全部原因是将对象转换为字符串,然后在两个端点之间交换这些字符数组。这样,您就可以解决围绕具有不同布局、格式、精度、字节序的对象的所有问题。
如果您绝对想传递指针,则构建设置必须相同。一切。所有编译器和链接器版本、设置、所有#defines、优化级别等......这是一条非常难以遵循的路径,并且是一个脆弱的解决方案。