You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost Serialize处理void指针二进制数据及TaskResults多态类序列化问询

Alright, let's break down your two Boost Serialization questions—they’re both common pain points when working with polymorphic types and raw binary data, so I’ll walk you through each solution clearly.


1. Handling Binary Data in a void* with Boost Serialization

Boost Serialize doesn’t natively support void* because it lacks type information to know how to process the data. The workaround is to explicitly serialize two things: the length of the binary blob, then the raw bytes themselves. Here’s how to implement this:

Core Approach

  • First serialize the size_t length value (so deserialization knows how much memory to allocate).
  • Use boost::serialization::binary_object to treat the void* memory as a raw byte stream, skipping type checks.

Example Implementation

#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/access.hpp>
#include <cstdlib> // for malloc/free

struct RawBinaryHolder {
    void* _data;
    size_t _dataLength;

    RawBinaryHolder(void* data = nullptr, size_t len = 0) : _data(data), _dataLength(len) {}

    ~RawBinaryHolder() {
        free(_data); // Clean up allocated memory
    }

private:
    friend class boost::serialization::access;

    template<class Archive>
    void save(Archive& ar, const unsigned int version) const {
        // Save the length first
        ar << _dataLength;
        // Save the raw binary data
        ar << boost::serialization::make_binary_object(_data, _dataLength);
    }

    template<class Archive>
    void load(Archive& ar, const unsigned int version) {
        // Load the length to know how much memory to allocate
        ar >> _dataLength;
        // Allocate memory (use smart pointers if you want safer management)
        _data = malloc(_dataLength);
        // Load the raw bytes into the allocated memory
        ar >> boost::serialization::make_binary_object(_data, _dataLength);
    }

    // Split save/load requires this macro to tell Boost about the separate methods
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};

Key Notes

  • Memory Management: You’re responsible for allocating/freeing memory during deserialization—use smart pointers or containers if you want to avoid manual leaks.
  • Binary Blob Handling: make_binary_object tells the archive to treat the memory as raw bytes, so no type validation occurs here.

2. Serializing the Polymorphic TaskResults Hierarchy

Your current setup has a critical quirk: the _data pointer in TaskResults points to internal storage of _specificData in the derived class. Serializing the raw _data pointer directly will result in invalid memory addresses during deserialization (since the new vector will live in a different spot). Instead, we need to serialize the actual vector data, then re-link the _data pointer after deserialization.

Step 1: Fix the Base Class

Boost Serialization requires polymorphic classes to have a virtual destructor. Also, we’ll adjust SetData to be protected so derived classes can access it:

class TaskResults {
public:
    void* _data;
    size_t _dataLength;

    // Add virtual destructor for polymorphic support
    virtual ~TaskResults() = default;

protected:
    void SetData(void* memAddr, size_t len) {
        _data = memAddr;
        _dataLength = len;
    }

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        // We don't serialize _data directly here—let the derived class handle the actual data
        // (The length is redundant since the derived class's vector holds all necessary info)
    }
};

Step 2: Implement Derived Class Serialization

We’ll serialize the _specificData vector, then update the base class’s _data pointer after deserialization. Also, we’ll fix a bug in your original GiveData function (you forgot to multiply by sizeof(float) for byte length):

#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>

class SpecificTaskResults : public TaskResults {
public:
    std::vector<float> _specificData;

    void GiveData(std::vector<float> computedData) {
        _specificData = std::move(computedData);
        // Fix: _dataLength should be in bytes, not number of elements
        SetData(_specificData.data(), _specificData.size() * sizeof(float));
    }

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        // Serialize the base class first
        ar & boost::serialization::base_object<TaskResults>(*this);
        // Serialize the actual vector data
        ar & _specificData;

        // After deserialization, re-link the base class's _data pointer
        if constexpr (Archive::is_loading::value) {
            if (!_specificData.empty()) {
                SetData(_specificData.data(), _specificData.size() * sizeof(float));
            } else {
                SetData(nullptr, 0);
            }
        }
    }
};

// Register the derived class with Boost so it recognizes polymorphism
BOOST_CLASS_EXPORT_KEY(SpecificTaskResults)

Step 3: Test the Serialization

Here’s how you’d use this in practice with binary archives:

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <fstream>
#include <cassert>

int main() {
    // Create and populate results
    SpecificTaskResults results;
    std::vector<float> sampleData = {1.5f, 2.7f, 3.9f};
    results.GiveData(std::move(sampleData));

    // Serialize to file
    std::ofstream ofs("task_results.bin", std::ios::binary);
    boost::archive::binary_oarchive oa(ofs);
    TaskResults* ptr = &results; // Polymorphic pointer
    oa << ptr;

    // Deserialize back
    std::ifstream ifs("task_results.bin", std::ios::binary);
    boost::archive::binary_iarchive ia(ifs);
    TaskResults* deserializedPtr = nullptr;
    ia >> deserializedPtr;

    // Verify the data
    SpecificTaskResults* deserializedResults = dynamic_cast<SpecificTaskResults*>(deserializedPtr);
    if (deserializedResults) {
        assert(deserializedResults->_specificData == std::vector<float>{1.5f, 2.7f, 3.9f});
        assert(deserializedResults->_data == deserializedResults->_specificData.data());
        assert(deserializedResults->_dataLength == 3 * sizeof(float));
    }

    // Clean up
    delete deserializedPtr;
    return 0;
}

Key Notes

  • Polymorphic Registration: BOOST_CLASS_EXPORT_KEY tells Boost about the derived class, so it can handle serialization/deserialization through base class pointers.
  • Deserialization Linking: The if constexpr check ensures we only re-link the _data pointer during loading, not saving.
  • Byte Length Fix: Always use byte count for raw data pointers—your original code used element count, which would lead to incorrect memory size calculations.

内容的提问来源于stack exchange,提问作者PhilipV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:13:19