【发布时间】:2020-06-28 22:18:10
【问题描述】:
我正在使用一些旧代码,这些代码会分配一块 RAM,然后将二进制文件加载到其中。二进制文件是一系列 8 位灰度图像平面 X x Y 大小,Z 平面深。这些文件通常在 500 MB 到 10 GB 之间。
现有代码使用复杂的指针排列来访问 XY、XZ 或 YZ 平面中的各个平面。
我想做的是用单个向量向量替换指针,其中每个子向量都是数据中的一个 XY 平面。这样做的目的是为了获得一些安全性并检查您使用向量而不是使用原始指针访问。
基于上一个问题 (Is it possible to initialize std::vector over already allocated memory?) 我有以下代码
//preallocate.h
template <typename T>
class PreAllocator
{
private:
T* memory_ptr;
std::size_t memory_size;
public:
typedef std::size_t size_type;
typedef T* pointer;
typedef T value_type;
PreAllocator(T* memory_ptr, std::size_t memory_size) : memory_ptr(memory_ptr), memory_size(memory_size) {}
PreAllocator(const PreAllocator& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};
template<typename U>
PreAllocator(const PreAllocator<U>& other) throw() : memory_ptr(other.memory_ptr), memory_size(other.memory_size) {};
template<typename U>
PreAllocator& operator = (const PreAllocator<U>& other) { return *this; }
PreAllocator<T>& operator = (const PreAllocator& other) { return *this; }
~PreAllocator() {}
pointer allocate(size_type n, const void* hint = 0) {return memory_ptr;}
void deallocate(T* ptr, size_type n) {}
size_type max_size() const {return memory_size;}
};
简化后的 main 函数如下所示:
TOMhead header;
uint8_t* TOMvolume;
size_t volumeBytes = 0;
int main(int argc, char *argv[])
{
std::fstream TOMfile;
std::ios_base::iostate exceptionMask = TOMfile.exceptions() | std::ios::failbit| std::ifstream::badbit;
TOMfile.exceptions(exceptionMask);
try {
TOMfile.open(argv[1],std::ios::in|std::ios::binary);
}
catch (std::system_error& error) {
std::cerr << error.code().message() << std::endl;
return ERROR;
}
TOMfile.read((char*) &header, sizeof(header));
if (!TOMfile)
{
std::cout<<"Error reading file into memory, expected to read " << sizeof(header) << " but only read " << TOMfile.gcount() << "bytes" <<std::endl;
return ERROR;
}
TOMfile.seekg(std::ios_base::beg); // rewind to begining of the file
TOMfile.seekg(sizeof(header)); // seek to data beyond the header
volumeBytes = (header.xsize * header.ysize * header.zsize);
std::cout << "Trying to malloc " << volumeBytes << " bytes of RAM" << std::endl;
TOMvolume = (uint8_t*) malloc(volumeBytes);
if (TOMvolume == NULL)
{
std::cout << "Error allocating RAM for the data" << std::endl;
return ERROR;
}
TOMfile.read((char*) TOMvolume,volumeBytes);
然后我尝试使用预分配器来创建一个包含这个 malloc 数据的向量
std::vector<uint8_t, PreAllocator<uint8_t>> v_TOMvolume(0, PreAllocator<uint8_t>(&TOMvolume[0], volumeBytes));
v_TOMvolume.push_back(volumeBytes);
但任何读取向量大小或向量中任何数据的尝试都会失败。当我只使用调试器查看数据时,内存中的数据是正确的,它只是没有与向量相关联,正如我所希望的那样。
有什么想法吗?我正在尝试做的事情可能吗?
【问题讨论】:
-
在我看来,您正在尝试使用此分配器方案来读取预分配的内存。它只是为了重用已经分配的内存,而不是读取它。每次
push_back(volumeBytes)时,您都将使用volumeBytes的任何值覆盖映射内存的 1 个字节。如果您的目标是读取TOMvalue中的内存,那么这种方法将不起作用。 -
而不是
mallocing 内存,然后尝试将其映射到std::vector,为什么不创建一个适当大小的std::vector并直接读取它? -
或者使用 Boost.MultiArray 的
boost::multi_array_ref怎么样(无论你真的想要一个多维数组还是一维切片)。 -
@aschepler 我正在考虑为此进行提升,但是当我上次查看时,与标准向量不同,没有明显的方法可以将文件直接读入多数组中。
-
@FrançoisAndrieux 我的目标是让一大块已经填充的内存看起来像并且可以通过向量访问。我尝试了几种方法,但无法让向量意识到它已经指向分配的数据,所以它认为它的大小为零。
标签: c++ multidimensional-array stdvector large-files