代码之家  ›  专栏  ›  技术社区  ›  andand

是否有一个安全的/标准的方式来管理C++中的非结构化内存?

  •  4
  • andand  · 技术社区  · 16 年前

    我正在构建一个玩具虚拟机,它需要一块内存来存储和访问不同类型和大小的数据元素。我通过在所需大小的uint8_t*数据块周围编写一个包装类来实现这一点。该类具有一些模板方法,可以在内存块中的任意位置写入/读取类型化数据元素,这两种方法都会进行检查以确保不会违反边界。这些方法使用memmove,我希望它或多或少是安全的。也就是说,虽然我愿意继续朝这个方向努力,但我必须相信,其他拥有更多专业知识的人以前也在这里,并且可能愿意分享他们的智慧。特别地:

    1)在C++标准(过去、现在、将来)中有一个类被定义为执行与上面所概述的功能类似的函数吗?

    2)如果没有,是否有一个(最好是免费的,如啤酒)图书馆?

    3)简而言之,除了边界检查和将一种类型写入内存位置并读取与该位置不同的内容这一不可避免的问题之外,还有其他我应该注意的问题吗?

    编辑

    下面是我试图做的简化(即析构函数和一些其他相关的方法);但它抓住了它的本质:

    
    #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++中还是在任何C++标准中)。我想让我不舒服的是在块类中传递“void*”参数(即使是受保护的成员),我正在寻找一种更安全的方法来实现这一点。

    谢谢。

    & & &;
    3 回复  |  直到 16 年前
        1
  •  5
  •   Nikolai Fetissov    16 年前

    嗯,因为你在C++中,听起来好像你在寻找 STL allocator 和/或 placement new .

        2
  •  1
  •   Ben Voigt    16 年前

    reinterpret_cast 但它需要适当的对齐, memmove 不。

        3
  •  1
  •   Michael Aaron Safyan    16 年前

    如果您分配一个数组 boost::variant ,然后您可以在每个位置允许多个不同的类型;但是,每个元素分配的空间量将等于所有可能类型的最大值。但是请注意,如果只使用基元类型和void*,那么这不会浪费太多空间。