2017-08-29 107 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;