Is there a safe / standard way to manage unstructured memory in C++?
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.
精彩评论