如何为数组结构的数组分配内存



所以我有一个如下所示的struct,我想创建一个该结构的数组并为其分配内存(使用malloc)。

typedef struct {
float *Dxx;
float *Dxy;
float *Dyy;
} Hessian; 

我的第一直觉是为整个结构分配内存,但我相信内部数组(DxxDxyDyy)不会被分配。如果我一个接一个地分配内部数组,那么数组的结构将是未定义的。现在我认为我应该为内部数组分配内存,然后为结构数组分配内存,但这对我来说似乎是错误的。我应该如何解决这个问题?

在这种情况下,我需要使用malloc而不是new/delete的逻辑,因为我必须在cuda中执行此操作,并且cuda中的内存分配是使用cudaMalloc完成的,这有点类似于malloc

在C++中,您根本不应该使用malloc,而应该使用newdelete,如果实际需要。从您提供的信息来看,事实并非如此,因为C++您也宁愿使用std::vector(或std::array)而不是 C 样式数组。也不需要typedef

所以我建议重写你的结构以使用向量,然后生成这个结构的向量,即:

struct Hessian {
std::vector<float> Dxx;
std::vector<float> Dxy;
std::vector<float> Dyy;
}; 
std::vector<Hessian> hessianArray(2); // vector containing two instances of your struct
hessianArray[0].Dxx.push_back(1.0); // example accessing the members

使用向量,您大部分时间不必担心分配,因为类会为您处理。hessianArray中包含的每个Hessian都会自动为您分配,存储在堆上,并在超出范围时销毁hessianArray

这似乎是可以使用 STL 容器解决的问题。关于您不知道可能使用的数组大小的事实std::vector.

它不易出错,更易于维护/使用,标准容器可以自行释放资源(RAII)。 @muXXmit2X已经展示了如何使用它们。

但是如果你有/想要使用动态分配,你必须首先为 X 结构数组分配空间

Hessian *h = new Hessian[X];

然后为所有结构中的所有数组分配空间

for (int i = 0; i < X; i++)
{
h[i].Dxx = new float[Y];
// Same for Dxy & Dyy
}

现在,您可以访问和修改它们。也不要忘记释放资源

for (int i = 0; i < X; i++)
{
delete[] h[i].Dxx;
// Same for Dxy & Dyy
}
delete[] h;

你永远不应该在 c++ 中使用 malloc。

为什么?

new将确保您的类型将调用其构造函数。虽然malloc不会调用构造函数。new关键字也更安全类型,而malloc根本不是类型安全的

正如其他答案所指出的,在 c++ 中应避免使用malloc(甚至new)。无论如何,正如您要求的那样:

在这种情况下,我需要使用malloc而不是new/delete的逻辑,因为我必须在cuda中执行此操作...

在这种情况下,您必须首先为Hessian实例分配内存,然后遍历它们并为每个DxxDxyDyy分配内存。我将为此创建一个函数,如下所示:

Hessian* create(size_t length) {
Hessian* obj = (Hessian*)malloc(length * sizeof(Hessian));
for(size_t i = 0; i < length; ++i) {
obj[i].Dxx = (float*)malloc(sizeof(float));
obj[i].Dxy = (float*)malloc(sizeof(float));
obj[i].Dyy = (float*)malloc(sizeof(float));
}
return obj;
}

要释放使用上述函数分配create内存,您必须遍历Hessian实例并首先DxyDyy释放每个Dxx,然后释放存储Hessian实例的块:

void destroy(Hessian* obj, size_t length) {
for(size_t i = 0; i < length; ++i) {
free(obj[i].Dxx);
free(obj[i].Dxy);
free(obj[i].Dyy);
}
free(obj);
}

注意:使用所介绍的方法将防止内存泄漏的责任转移给您。


如果您希望使用std::vector而不是手动分配和取消分配(强烈建议这样做),您可以为其编写一个自定义分配器以使用它cudaMalloccudaFree如下所示:

template<typename T> struct cuda_allocator {
using value_type = T;
cuda_allocator() = default;
template<typename U> cuda_allocator(const cuda_allocator<U>&) {
}
T* allocate(std::size_t count) {
if(count <= max_size()) {
void* raw_ptr = nullptr;
if(cudaMalloc(&raw_ptr, count * sizeof(T)) == cudaSuccess)
return static_cast<T*>(raw_ptr);
}
throw std::bad_alloc();
}
void deallocate(T* raw_ptr, std::size_t) {
cudaFree(raw_ptr);
}
static std::size_t max_size() {
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
};
template<typename T, typename U>
inline bool operator==(const cuda_allocator<T>&, const cuda_allocator<U>&) {
return true;
}
template<typename T, typename U>
inline bool operator!=(const cuda_allocator<T>& a, const cuda_allocator<U>& b) {
return !(a == b);
}

自定义分配器的用法非常简单,您只需将其指定为std::vector的第二个模板参数:

struct Hessian {
std::vector<float, cuda_allocator<float>> Dxx;
std::vector<float, cuda_allocator<float>> Dxy;
std::vector<float, cuda_allocator<float>> Dyy;
};
/* ... */
std::vector<Hessian, cuda_allocator<Hessian>> hessian;

相关内容

  • 没有找到相关文章