所以我有一个struct
,如下所示,我想创建一个该结构的数组并为其分配内存(使用malloc
)。
typedef struct {
float *Dxx;
float *Dxy;
float *Dyy;
} Hessian;
我的第一直觉是为整个结构分配内存,但是,我相信内部数组(Dxx
,Dxy
,Dyy
)将不会被分配。如果我逐个分配内部数组,那么数组的结构将是未定义的。现在我想我应该为内部数组分配内存,然后为结构数组分配内存,但对我来说似乎是错误的。我该如何解决这个问题?
我需要在这种情况下使用malloc
而非new
/ delete
的逻辑,因为我必须在cuda中执行此操作并在{{3}中进行内存分配}使用cudaMalloc
完成,这有点类似于malloc
。
答案 0 :(得分:3)
在C ++中,您根本不应使用malloc
,而是在必要时使用new
和delete
。从你提供的信息来看,它不是,因为在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
使用向量,您不必担心大多数时间的分配,因为类会为您处理。 Hessian
中包含的每个hessianArray
都会自动为您分配,存储在堆上并在hessianArray
超出范围时销毁。
答案 1 :(得分:2)
似乎可以使用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
不类型安全。
答案 2 :(得分:1)
正如其他答案所指出的那样,c++应避免使用malloc
(甚至new
)。无论如何,正如你所要求的那样:
我需要在这种情况下使用
malloc
而不是new
/delete
的逻辑,因为我必须在cuda中执行此操作...
在这种情况下,您必须首先为Hessian
个实例分配内存,然后通过它们进行迭代并为每个Dxx
,Dxy
和Dyy
分配内存。我会为此创建一个函数,如下所示:
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
个实例并首先释放每个Dxx
,Dxy
和Dyy
,然后解除分配存储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
代替手动分配和解除分配(强烈推荐),您可以write a custom allocator使用cudaMalloc
和cudaFree
之类的如下:
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;