2017-08-29 106 views
1

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

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

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

我需要在这种情况下使用malloc代替new/delete逻辑,因为我在为此在和内存分配使用cudaMalloc,这有点类似于malloc完成。

+0

您通过学习如何使用'std :: vector'来解决问题,并让C++库为您完成工作。有关更多信息,请参阅C++书籍。 –

+0

不要。使这些成员'std :: vector's,然后有这些结构的'std :: vector'。 – NathanOliver

+3

首先从不在C++中使用'malloc'。其次,为什么不使用['std :: vector'](http://en.cppreference.com/w/cpp/container/vector)?或者,甚至可能[[std :: array]](http://en.cppreference.com/w/cpp/container/array)如果大小是固定的,并在编译时已知? –

回答

3

在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超出范围时销毁。

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; 

你应该从未使用malloc在

为什么?

new将确保您的类型将有他们的构造函数调用。而malloc将不会调用构造函数。 new关键字也更安全,而malloc而不是类型安全。

+0

_它会确保你的类型将他们的构造函数叫做._你的意思是'new',对吧?你写它的方式,听起来像'malloc'会调用构造函数,它不会。 – muXXmit2X

+1

大家有点误导。我修好了。 –

1

正如其他答案指出的,应该避免在中使用malloc(或甚至new)。无论如何,你的要求:

我需要在这种情况下,而不是new/delete使用malloc逻辑,因为我不得不这样做在 ...

在这种情况下,你必须首先为Hessian实例分配内存,然后遍历它们并为每个Dxx,DxyDyy分配内存。我会为这个像下面创建一个函数:

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实例迭代和释放每个DxxDxyDyy,然后再解除分配块,存储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它使用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;