2015-08-26 63 views
-2

我正在嘗試處理一些相當大的二進制文件(每個文件最多20GB)。要做到這一點,我想分塊讀取它們,處理並寫入新文件。二進制文件fread/fwrite和calloc/free內存泄漏?

爲了讀取文件,我使用:

fp = fopen(filename,"rb"); //open binary file to read 
fseek(fp, start_of_chunk, SEEK_SET); //set cursor to current chunk 
fread(data,size_of_chunk,1,fp); //read one chunk of data 
fclose(fp); 

我然後使用釋放calloc分配一些陣列和處理數據。 把它寫回,我用:

fout = fopen(file_out,"ab"); //open output binary file in append mode 
fwrite(processed_data,size_of_processed_data,1,fout); 
fclose(fout); 

最後,我用免費的()在每個分配的變量(最大的一個是讀取數據塊(〜400 MB),最小的一個是關於1kB的)並開始閱讀下一個塊。

輸出工作正常,但進程保持進食記憶像沒有明天。一個800 MB的測試文件最多可以容忍6 GB的RAM,穩步增長。一次讀取整個文件幾乎與讀取塊相同的內存量。即使這些變量包含99%的數據,在循環之間使用free()也不會釋放已使用內存的5%。

由於我對C編程非常陌生,有什麼我可能會失蹤?我在另一個線程中看到,操作系統(我的情況是Windows 10 x64,Windows 7 x64上的相同問題)可能太慢而無法釋放內存。閱讀更大的塊在我的情況下沒有幫助。所有文件句柄在讀/寫後都會關閉,所有分配的數組在最後釋放。

編輯:我在循環內分配多次。我正在使用

free(data); 
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t)); 

每次調用讀取數據之前。處理大塊的某個部分,我正在使用

data_part = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t)); 
memmove(data_part,pointer_to_part_of_chunk, size_of_data_part); 

編輯2:我改變了一些東西,感謝評論。儘管如此,內存負載仍然穩步上升(比以前減慢)。下面的代碼再次:​​

//initiate variables 
//allocate arrays 
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t)); 
array1 = (uint16_t*)calloc(number_of_elements1,sizeof(uint16_t)); 
array2 = (uint16_t*)calloc(number_of_elements2,sizeof(uint16_t)); //and so on 

//some precalculations 

//start of the loop 
while (not_end_of_the_file){ 
    fp = fopen(filename,"rb"); //open binary file to read 
    fseek(fp, start_of_chunk, SEEK_SET); //set cursor to current chunk 
    fread(data,size_of_chunk,1,fp); //read one chunk of data 
    fclose(fp); 

    //calculate stuff 
    start_of_chunk = start_of_chunk + increment; 
    for (i=0;i<I;i++){ 
     memmove(array1,pointer_to_part_of_data, size_of_array1); 
     if (statement){ 
      subfunction1(array1); 
     } 
     else{ 
      subfunction2(array1); 
     }; //nothing more than some for loops, if statements and arithmetic operations 
    //NO further allocations here, all buffers will be reused 
    }; 

    //write result 
    fout = fopen(file_out,"ab"); //open output binary file in append mode 
    fwrite(processed_data,size_of_processed_data,1,fout); 
    fclose(fout); 
}; 

有一些分配的子功能發生,但內存應該釋放的子功能完成後,不應該嗎?

+2

我們需要看到更多的代碼。聽起來好像你可能會在循環中重複分配內存,而不是隻重複使用一次。 – Barmar

+2

很確定你在代碼中做錯了什麼,但你沒有向我們展示過。請發佈[MCVE](http://stackoverflow.com/help/mcve)。 – user3386109

+0

@Barmar我確實多次分配。我會嘗試添加更多的代碼。 – Dominic

回答

0
free(data); 
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t)); 

確定的data在自由行值從以前的調用的返回值來釋放calloc?如果免費通話時是NULL,那是空操作。

+0

不,我不是。我沒有意識到這可能與之前分配的值不同。我確實刪除了免費電話,並將所有分配轉移到循環之外(請參閱最新的編輯)。儘管如此,內存使用量在計算期間仍然在增加,即使它只應覆蓋現有數組。 – Dominic