2014-09-22 36 views
1

在我開始之前,是的,我已閱讀a possible duplicate,malloc being weird in linux,cplusplus.com on malloc,並在谷歌上進行了一些搜索。malloc可以依靠返回連續的內存,我該如何正確地調用它?

我有一個科學計算問題,需要一個非常大的二維數組。我正在使用「C語言中的數字食譜」副本中的代碼,並且在我的2D數組中出現未分配內存的問題。我在Windows中工作,並且正在使用C++與MSVC 2012

這裏是我的二維數組分配

unsigned long nrl=0; 
    unsigned long nrh=749774; 
    unsigned long ncl=0 
    unsigned long nch=250657; 
    unsigned long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 
    double **m; 
    if((size_t)(nrow*ncol)<(size_t)nrow){ 
    m=NULL; 
    return m; 
    } 
    /*allocate pointers to rows*/ 
    m=(double **)malloc((size_t)(nrow)*sizeof(double*)); 
    if (!m){ 
    m=NULL; 
    return m; 
    } 

    /*allocate rows and set pointers to them*/ 
    m[nrl]=(double *) malloc((size_t)((nrow*ncol)*sizeof(double))); 
    if(!m[nrl]){ 
    free(m[nrl]); 
    free(m); 
    m=NULL; 
    return m; 
    } 
    for(i=nrl+1;i<=nrh;i++)m[i]=m[i-1]+ncol; 
    /*The 2D array should now be callable as m[nrow][ncol]*/ 
    /*Pseudo-code below*/ 
    m[0][0] == Good, allocated memory 
    m[125][200923] == Unallocated, crashes program 
    m[nrh-1][nch-1] == Good, allocated memory 

我目前依靠malloc的,如果內存分配失敗,返回NULL(我的確得到NULL值,如果我嘗試分配非常非常大的陣列。

此外,我試圖double *m = new double[nch*nrh],但這給了我一個內存分配錯誤。我接受任何建議的替代實現,但我需要能夠知道是否能夠分配工作並在必要時重新分配較小的塊。

編輯:

這是一個c函數,但我的大部分代碼是在C++中。

更新:

感謝大衛,我能夠解決這個問題。從

if((size_t)(nrow*ncol)<(size_t)nrow) 

改變我的溢出檢查

if(SIZE_MAX/nrow < ncol || SIZE_MAX/ncol < nrow || nrow*ncol<nrow) 

允許malloc的時候就應該失敗。

+2

awell你試圖分配1.36 tebibytes的數據,所以是的,那會給你一個分配錯誤。 – IdeaHat 2014-09-22 14:30:48

+0

對'((size_t)nrow)*((size_t)ncol)'比'(size_t)(nrow * ncol)'更有意義。 – chux 2014-09-22 14:31:19

+0

不需要施放我的想法。他們最終是'int'。如果數組很大,你應該注意溢出問題。如果它很大,我認爲你不需要考慮連續分配,因爲只有當你的所有數據都適合緩存時才希望它是連續的。 – HuStmpHrrr 2014-09-22 14:44:46

回答

3

我猜你有32位程序。請注意0​​是(很多!)大於2^32。你實際上正在嘗試分配1400 GB,我想它對你來說是一個驚喜。

最有可能不可能分配那麼多的內存,當然不是在一個32位的進程。您的代碼似乎運行,因爲(nrow*ncol)*sizeof(double)遭受整數溢出,所以您致電malloc成功,但不分配您所期望的內存。實際上,即使在64位過程中,也會發生溢出,因爲nrow*ncol使用32位算術進行評估,因爲您將nrowncol聲明爲unsigned long。他們應該真的是size_t

無論如何,你將需要重新考慮你的整個方法來解決你的問題。你真的可以期望用1400 GB密集矩陣做任何有用的事嗎?

+0

注意:DOS 16位機器(大內存模式)可以分配大於64k的內存。 IOW作爲「32位機器」不會將內存限制爲4Gbyte。內存容量雖然通常與擁有者整數大小有關,但是是獨立因素。 – chux 2014-09-22 14:37:08

+0

32位或64位在這種情況下並不重要......當然,您可以在64位地址空間中容納1.36 tebibytes,但Windows 8只支持512位gibibytes。 Windows Server 2012最多可以支持4個tebibibytes,但我猜測如果這個人可以負擔得起這個硬件,那麼問題就會大不相同。 – IdeaHat 2014-09-22 14:37:48

+0

@MadScienceDreams好吧,它的確很重要,因爲失敗模式是不同的。在64位上,對malloc的調用會失敗,因爲至少傳遞的'size_t'是預期的值。 – 2014-09-22 14:39:37

相關問題