2017-03-23 91 views
-1

所以我目前正在閱讀的光線追蹤,想考出了幾件事情我自己,看看我理解的概念。我查了一下如何從http://netpbm.sourceforge.net/doc/ppm.html寫一個簡單的ppm文件。C++動態數組的大小

我使用視覺工作室2015和存儲的RGB值中的2D陣列的每個像素。圖像的分辨率是720p,每個像素有3個整數用於紅色,綠色和藍色,所以我製作的陣列看起來像int[720*1280][3]

我計算出內存的總使用量應該是4字節(對於指向2D數組的指針)+ 720 * 1280 *(4 + 3 * 4)字節(對於指向數組的720 * 1280指針有3個整數),大約14mb。

當我檢查在Visual Studio中的內存使用它說,它採用左右的內存60MB。我想問的是額外的36 MB來自哪裏?

的main.cpp

#include <iostream> 

#include "PPM.h" 


int main(int argc, char **argv) 
{ 
    // WIDTH AND HEIGHT OF THE IMAGE 
    const int width = 1280; 
    const int height = 720; 

    // 3 RGB VALUES FOR EACH PIXEL 
    const int rgb = 3; 

    // CREATE A BUFFER TO HOLD THE DATA 
    int **data = allocateBuffer(width, height, rgb); 

    // FILL IN THE BUFFER 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      data[y*width + x][0] = x %255; 
      data[y*width + x][1] = y %255; 
      data[y*width + x][2] = 0; 
     } 
    } 

    // WRITE THE DATA TO A FILE 
    saveImage("Test.ppm", width, height, data); 

    // DELETE THE BUFFER 
    deleteBuffer(data, width*height); 

    // WAIT FOR INPUT TO EXIT 
    std::cout << "Press ENTER key to exit\n"; 
    std::getchar(); 
    return 0; 
} 

PPM.h

#pragma once 

// WRITES THE DATA TO THE FILE 
extern void saveImage(char *filename, int width, int height, int **data); 

// CREATES A BUFFER TO HOLD THE DATA 
extern int** allocateBuffer(int width, int height, int rgbAmnt); 

// RELEASES THE MEMORY 
extern void deleteBuffer(int **buffer, int size); 

PPM.cpp

#include "PPM.h" 
#include <fstream> 

// WRITES THE DATA TO THE FILE 
void saveImage(char *filename, int width, int height, int **data) 
{ 
    std::ofstream file; 
    file.open(filename); 
    file << "P3" << "\n" << width << " " << height << "\n255\n"; 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      file << data[y*width + x][0] << " " << data[y*width + x][1] << " " << data[y*width + x][2] << "\n"; 
     } 
    } 
    file.close(); 
} 

// CREATES A BUFFER TO HOLD THE DATA 
int** allocateBuffer(int width, int height, int rgbAmnt) 
{ 
    int size = width * height; 
    int **data = new int*[size]; 
    for (int i = 0; i < size; i++) 
    { 
     data[i] = new int[rgbAmnt]; 
    } 
    return data; 
} 

// RELEASE THE MEMORY 
void deleteBuffer(int **buffer, int size) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     delete[] buffer[i]; 
    } 
    delete[] buffer; 
} 
+0

我非常懷疑你的程序只聲明一個變量。其次,您的計算不包括用於調試內存損壞和任何可能發生的填充字節的「guard字節」之類的任何額外開銷。 – PaulMcKenzie

+1

註釋掉數組聲明,然後查看內存使用情況。 – Barmar

+0

在考慮我的計算後,我覺得內存使用量應該低得多(應該是1280 * 720 * 16)+ 4,大概是14mb。該計劃非常小巧,只有4個函數,聲明瞭幾個int和一個c-string。我有一個主函數,1個函數分配數組和一個函數來刪除它。最後一個函數只是將數據寫入文件using和ofstream。我試着看看我是否可以添加代碼。 –

回答

0

幾句話,磨片ñ你要求一個記憶塊,你通常得到超過你的要求。即使你不知道。

發生這種情況的原因有幾個。下面是其中一些:1,爲性能:多個處理器運行速度更快,如果內存塊是對準沿着一些界限,這意味着塊地址是多一些整數(通常是2的冪)的;第二,對於粒度,這意味着較低級別的軟件(OS和您的程序的運行時庫)更喜歡管理最小大小的塊;和第三個爲內存本身的管理,這意味着較低級別的軟件將爲您的數據塊添加標題(前綴)和可能的預告片(或後綴)。他們將獲得將讓這些數據塊得到分配和解放的信息,並可能進行一些驗證。

例如,分配的數據塊的大小,指向下一個塊的指針,以及頭和尾的校驗和,以確保它們不會被粗心或惡性程序損壞。

+0

感謝您的回答。我讀過分配內存時有一些填充,但我只希望它最多隻有幾個字節。也許它的計算結果是錯誤的,實際使用的內存量實際上接近60個字節。 –

+0

請考慮你的allocateBuffer例程。在那裏你分配了很多3-int數組。這有很多開銷,對吧?有填充和標題(也許拖車)爲他們每個人。 也許你可以將它們轉換成更大的內存塊,並使用指針算術來訪問它的各個組件。 你覺得呢? –

+0

閱讀你的評論後,我改變了緩衝區是一個一維數組,我現在的內存使用下降到11MB左右。非常感謝你。那麼是否可以在可能的情況下使用一維數組,因爲這樣可以節省內存? –