Существует ли безопасный / стандартный способ управления неструктурированной памятью в C ++? - PullRequest
4 голосов
/ 13 апреля 2010

Я создаю игрушечную виртуальную машину, для которой требуется блок памяти для хранения и доступа к элементам данных разных типов и разных размеров. Я сделал это, написав класс-оболочку вокруг блока данных uint8_t * нужного размера. Этот класс имеет несколько шаблонных методов для записи / чтения типизированных элементов данных в / из произвольных мест в блоке памяти, которые проверяют, чтобы убедиться, что границы не нарушены. Эти методы используют memmove, как я надеюсь, более или менее безопасно. Тем не менее, хотя я и хочу идти в этом направлении, я должен верить, что другие, обладающие большим опытом, были здесь раньше и могли бы поделиться своей мудростью. В частности:

1) Есть ли класс в одном из стандартов C ++ (прошлое, настоящее, будущее), который был определен для выполнения функции, аналогичной описанной выше?

2) Если нет, есть ли (желательно бесплатная, как в пиве) библиотека, которая это делает?

3) Кроме этого, помимо проверки границ и неизбежной проблемы записи одного типа в ячейку памяти и чтения отличного от этого места, есть ли другие проблемы, о которых мне следует знать?

EDIT

Вот упрощение (то есть деструктор и некоторые другие связанные методы опущены) того, что я пытаюсь сделать; но он отражает суть этого:


#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;
}

Итак, я думаю, к чему я действительно стремлюсь, есть ли доступные библиотеки классов (как в стандартах C ++, так и вне их), которые по существу предоставляют эту функциональность. Полагаю, что меня это не устраивает, так это передача параметров void * (даже защищенных членов) в классе блоков, и я ищу более безопасный способ сделать это в общем.

Спасибо

-. &&

Ответы [ 3 ]

5 голосов
/ 13 апреля 2010

Хм, поскольку вы находитесь на C ++, звучит так, будто вы ищете STL allocator и / или размещение new.

1 голос
/ 13 апреля 2010

Если вы выделите массив boost :: variable , то вы можете разрешить несколько разных типов в каждой позиции; однако количество места, выделенного на элемент, будет равно максимуму для всех возможных типов. Обратите внимание, что если вы используете только примитивные типы и void *, то это не будет тратить так много места.

1 голос
/ 13 апреля 2010

Есть reinterpret_cast, но для этого требуется правильное выравнивание, memmove нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...