开发者

Is there a safe / standard way to manage unstructured memory in C++?

开发者 https://www.devze.com 2022-12-27 04:18 出处:网络
I\'m building a toy VM that requires a block of memory for storing and accessing data elements of different types and of different sizes.I\'ve done this by writing a wrapper class around a uint8_t* da

I'm building a toy VM that requires a block of memory for storing and accessing data elements of different types and of different sizes. I've done this by writing a wrapper class around a uint8_t* data block of the needed size. That class has some template methods to write / read typed data elements to / from arbitrary locations in the memory block, both of which check to make certain the bounds aren't violated. These methods use memmove in what I hope is a more or less safe manner. That said, while I am willing to press on in this direction, I've got to believe that other with more expertise have been here before and might be willing to share their wisdom. In particular:

1) Is there a class in one of the C++ standards (past, present, future) that has been defined to perform a function similar to what I have outlined above?

2) If not, is there a (preferably free as in beer) library out there that does?

3) Short of that, besides bounds checking and the inevitable issue of writing one type to a memory location and reading a different from that location, are there other issues I should be aware of?

EDIT

Here's a simplification (i.e. destructor and some other related methods ommitted) of what I'm trying to do; but it captures the essense of it:


#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <iostream>

class block
{
private:
    uint8_t *data;
    size_t size;

protected:
    block(const void* src, size_t size)
        : data(new uint8_t[size]), size(size) { ::memmove(data, src, size); }

    void set(const void* src, size_t dst_adr, size_t len)
    {
        assert( (size > dst_adr) && (size >  len) && ( (size - len) > dst_adr) );
        ::memmove(data+dst_adr, src, len);
    }

    void* get(size_t src_adr) const
    {
        assert( size > src_adr );
        return data+src_adr;
    }

public:
    block(size_t size) : data(new uint8_t[size]), size(size) {}

    size_t get_size() const { return this->size; }

    virtual void copy(const block& src, size_t src_adr, size_t dst_adr, size_t len)
    {
        // Bounds check
        assert( (size > dst_adr) && (size >= len) && ( (size - len) >= dst_adr) );
        assert( (src.size > src_adr) && (src.size >= len) && ( (src.size - len) >= src_adr) );
        ::memmove(data+dst_adr, src.data+src_adr, len);
    }
};

template <typename T>
class typed_block : public block
{
public:
    typed_block(const T& val) : block(&val, sizeof(T)) {}

    // Could use reinterpret_cast here instead, per Ben Voigt below
    operator T () const { return *((T*) this->get(0)); }

    typed_block<T>& operator=(const T& val)
    {
        this->set(*val, 0, get_size());
        return *this;
    }
};

int main(int argc, char** argv)
{
    block db(512);
    typed_block<long> x(1 << 30);
    typed_block<short> y(0);

    db.copy(x, 0, 15, x.get_size());
    y.copy(db, 17, 0, y.get_size());

    std::cout << "x = " << x << "\ty = " << y << std::endl;

    return 0;
}

So, I guess what I'm really getting at, are there class libraries available (either in or out of any C++ standards) that provide essentially this functionality. I guess what makes me uncomfortable with this is passing "void *" parameters (even as protected members) in the block class, and I'm looking for a safer way to do this in general.

开发者_如何学运维

Thanks.

-&&


Hmm, since you are in C++, it sounds like you are looking for STL allocator and/or placement new.


There's reinterpret_cast, but it requires proper alignment, memmove doesn't.


If you allocate an array of boost::variant, then you can allow multiple different types at each position; however, the amount of space allocated per element will be equal the maximum for all the possible types. Note though, that if you only use the primitive types and void*, then that doesn't waste that much space.

0

精彩评论

暂无评论...
验证码 换一张
取 消