2009-10-19 62 views
1

簡單的問題,我在書面方式,需要打開巨大的圖像文件(8kx8k)中的程序,但我對如何初始化巨大的陣列在C來保持圖像的有點困惑++ 。C++數組大小的x86和x64的

我一直在嘗試這樣的事:

long long SIZE = 8092*8092;  ///8096*8096 
double* array; 
array = (double*) malloc(sizeof(double) * SIZE); 
if (array == NULL) 
{ 
    fprintf(stderr,"Could not allocate that much memory"); 
} 

但有時我NULL檢查沒有趕上該數組沒有初始化,任何想法,爲什麼?

而且在X64的機器了12 GB的RAM,任何想法,爲什麼運行的時候,我不能初始化超過2個或3個數組,甚至?

我真的希望不要有代替陣列的部分工作。歡迎任何幫助。

謝謝。

+0

如果您在Windows下,請查看Address Windowing Extensions:http://msdn.microsoft.com/en-us/library/aa366527(VS.85).aspx – Artelius 2009-10-19 11:29:09

+3

注意:'malloc'是C方式分配內存,在C++中你應該使用'new'。 – Jesper 2009-10-19 11:41:52

+5

可能是一個錯字,但仍然是:「8k」應該可能是8 * 1024,即8192.「8096」的讀法類似於4k(4096)和8k的混合。 – unwind 2009-10-19 11:43:32

回答

2

你編譯應用程序作爲32位應用程序(在Visual Studio中的默認,如果這是你使用的是什麼),或作爲64位應用程序?如果您將其構建爲64位應用程序,則不應該有麻煩。

malloc分配(保留內存並返回一個指針),calloc初始化(將全部零寫入該內存)。

+0

BINGO!謝謝。 :-D – StfnoPad 2009-10-19 14:11:33

3

您可能會運行到2GB的每個進程的地址空間限制,如果你正在運行32位操作系統。用幾百MB的系統庫和其他東西,以及2或3個512MB的數組,這將容易得到2GB。一個64位的操作系統將幫助你。

+0

「...即使在具有12 GB RAM的x64機器中運行」-1 – sbi 2009-10-19 11:51:56

+1

硬件是否爲x64無關緊要。如果操作系統是32位,每進程地址空間爲32位,即使它使用PAE來運行一打2GB進程,每個進程仍然限制在2GB的限制內。 – ndim 2009-10-19 11:55:47

+0

他有12GB的系統內存,我敢打賭他已經在使用64位操作系統。 – AntonioMO 2009-10-19 12:07:04

4

你沒有運行到一個數組的大小問題。 8K * 8K僅爲64M。即使64M雙打(sizeof == 8)也不是問題;那隻需要512 MB。現在,一個32位應用程序(無論它在哪裏運行)應該能夠分配其中的一些。不是8,因爲操作系統通常需要爲自己保留一些空間(通常略高於2GB),有時甚至在內存碎片時不會保留3。

的「malloc的失敗,但沒有返回NULL」的行爲是Linux配置錯誤,通過# echo 2 > /proc/sys/vm/overcommit_memory

+0

是的,它是每個陣列512 MB。最後我發現錯誤,我正在使用Visual Studio 2008 C++進行編譯,並且在x86而不是x64下進行編譯。雖然vista如何檢查NULL是很奇怪的,但我想這也是Windows Vista中的一個bug。 : -/-------幾乎給了你正確的答案,但決定把它交給digitalarbeiter,因爲他提醒我不要繼續混用C++。不管怎麼說,還是要謝謝你。 – StfnoPad 2009-10-19 14:09:09

+0

Vista不需要檢查,你這樣做。 Linux的錯誤實際上是一個錯誤,即malloc返回一個非NULL指針,儘管分配內存失敗。這意味着即使是正確的程序也不能檢查'malloc'是否成功。 – MSalters 2009-10-20 07:48:45

1

似乎是,你必須在C運行時這樣的尺寸沒有連續的內存塊(500MB的〜)固定堆。嘗試將圖像映射到進程地址空間,而不是將文件複製到內存中。您只能映射文件的必要部分。

4

的malloc()未初始化的內存,它只是保留它。你必須明確地初始化它,例如通過從string.h中的memset():

array = (double*) malloc(SIZE * sizeof(double)); 
if (array) memset(array, 0, SIZE * sizeof(double)); 

然而,在C++中應該使用新代替的malloc

double* array = new double[SIZE]; 
if (!array) { 
    cerr << "Could not allocate that much memory" << endl; 
} 
for (int i=0; i<SIZE; i++) array[i] = 0.0; 

關於尺寸:每個這樣的陣列爲512 MB。你肯定確定你需要雙精度(這意味着圖像具有64位像素深度)?也許浮動就足夠了?這會減少內存佔用量。

+0

是否有任何理由在C中使用'memset'並在C++中使用循環? – 2009-10-19 12:31:22

+0

感謝提醒我不要將c與C++混合使用:-D – StfnoPad 2009-10-19 14:09:54

+0

實際上,malloc與使用數組一樣多的C++ ...在C++中,您顯然會使用一個向量來執行此類任務:std :: vector array( SIZE,0.0); //然後你只需要抓住std :: bad_alloc – 2009-10-19 15:16:38

0

我真的希望不要有代替陣列的部分工作。歡迎任何幫助。

你有沒有看着內存映射文件?

1

正如一個側面說明:雖然你不想打擾整個圖像在內存不是一次,有理由不這樣做。也許想想一個抽象,讓你只保留當前需要的內存塊。然後程序代碼可以被編寫爲對內存問題一無所知。

0

我建議使用壓縮。解壓縮它的一部分,您需要在代碼中進行處理,並在部件完成後進行壓縮。

第二個建議:編寫代碼來重載內存指針「operator +」和「operator-」,以便可以使用非連續內存緩衝區。使用較小的內存緩衝區會使您的代碼比連續較大的代碼更穩定。我曾經體驗過它,並寫過一些運算符重載,例如http://code.google.com/p/effoaddon/source/browse/trunk/devel/effo/codebase/addons/mem/include/mcur_i.h。當我在x86_64上測試47G malloc()ed系統內存時,我爲malloc()調用分配了1G,所以我總共分配了47個內存塊。編輯:雖然如果我試圖通過只使用一個malloc()儘可能多地分配,我只會在48G系統上獲得30G,也就是說不到70%,這是因爲每個malloc()要求更大的緩衝區,更多的管理內存由系統/ libc本身消耗,您知道,我調用了mlock()來防止將分配的內存換出到磁盤。

第三個:嘗試posix文件映射,映射到每個映像的內存。 (通過編寫C++調用malloc()比new()更穩定,因爲當內存受到壓力時,new()容易拋出異常而不是返回NULL。