2013-03-22 71 views
3

這是我在C++編寫代碼分段故障初始化INT **

int** a; 
try{ 
    a = new int*[m]; 
    for(int i = 0; i<m;i++) 
    a[i] = new int[n]; 
} 

... 現在我初始化上述使用循環如下:

for(int i = 0; i<m; i++) 
    for(int j = 0; i<n; j++) 
     a[i][j] = 0; 

我想提高性能,因此認爲使用memset是個好主意。所以修改我的代碼使用memset而不是for循環如下:

memset(a, 0, sizeof(a[0][0]) * m * n); 

但我得到分段錯誤執行此操作。任何人都可以幫我弄清楚我做錯了什麼嗎?

+0

你是否在代碼的任何地方爲「a」分配內存? – 2013-03-22 18:59:11

+0

對不起,我錯過了添加內存分配。 'a = new int * [m]; for(int i = 0; i user2175966 2013-03-22 19:03:44

+0

好的,現在問題很明顯 - 增加了一個答案。 – 2013-03-22 19:08:57

回答

3
int** a; 

這只是給你一個單一的對象。 A int**對象。它根本沒有指向任何地方。沒有int s分配給。當您開始將int分配爲存在時,您會收到未定義的行爲。

此外,int**指向的內存佈局的int秒的「二維數組」是像這樣:在的int*秒的陣列的第一個元素的int**點,以及在所述第一元件的int*小號點在一排int s。該內存不是連續的,因爲它需要間接地跳轉內存,即它不是一個單獨的內存塊。你不能用memset來寫信給它。

如果你只是想的int個固定的編譯時大小的二維數組,這樣做:

int a[N][M]; 

其中NM是常量表達式。這連續存儲,但我仍然不建議使用memset

或者使用標準容器,比如:

std::array<std::array<int, M>, N> a; 

如果你需要動態大小的它,嘗試:

std::vector<std::vector<int>> a(M, std::vector<int>(N)); 

或者,你可以用你int**動態地堅持,並確保你分配int* s和int s:

int** a = new int*[M]; 
for (i = 0; i < N; i++) { 
    a[i] = new int[N]; 
} 

但這很醜陋!

+0

'int a [N] [M];' - 仍然是C99的一部分,也可以作爲GCC的擴展,變長數組不是C++標準的一部分。 – LihO 2013-03-22 19:05:00

+0

@LihO其中'N'和'M'是常量表達式。 – 2013-03-22 19:05:31

+0

你現在我使用剛剛描述的醜陋的部分。所以會改進它 – user2175966 2013-03-22 19:10:16

1

使用int **您通常不會有單個連續的內存塊。假設你正確使用它,你會得到一個指針數組。這些指針中的每一個都會爲它分別分配一個數組。

既然如此,則無法將您的循環轉換爲單個memset(並且仍然會獲得定義的行爲)。

0

我覺得問題是內存沒有分配給實際存儲。變量a只是指針(除此之外未初始化)。它指向哪個地方?

3
int** a; 

只是指向指向int的指針的指針。

「現在我初始化上述使用循環」

你是不是在你的for環路初始化它,你只是想分配0的元素,唐」 t存在,這產生了未定義的行爲。您需要可以動態分配內存,這些元素或者還甚至更好:使用std::vector代替:

std::vector< std::vector<int> > a(m, std::vector<int>(n, 0)); 

「我試圖提高性能」

不要那樣做除非有必要。 不要過早優化。


編輯:之後你提到你已經面臨性能問題,這裏是你能做什麼:除了這個兩維C風格的數組:

int** a = new int*[m];  // m = number of rows 
for(int i = 0; i < m; i++) 
    a[i] = new int[n];  // n = number of columns 

你可以用一維std::vector

std::vector<int> vec(rows * cols, 0); 
... 
vec[i * cols + j] = 7; // equivalent of vec[i][j] 
這樣會有更多的優點:
  • 您的2D陣列將被存儲的存儲器中的連續塊內
  • 的存儲器的這個塊將在一次被分配,而不是在許多小塊
  • 元件的頻繁訪問會更快由於空間局部性
    (即是「近」的元素將在高速緩存存儲器提供這樣的
    程序將不必從主內存中加載它們)
  • 你會不會負責內存管理
    (內存一旦vector對象被破壞將被自動清理)
+0

我試圖優化它使用for循環的主要原因是花費很長時間,我必須減少它 – user2175966 2013-03-22 19:15:14

+0

你確定'for'循環需要很多時間?你是否用最近的編譯器(例如GCC 4.7或4.8中的'g ++')和啓用優化(例如'-O2'或'-O3')編譯? – 2013-03-22 19:20:22

+0

我現在看到了區別。我編譯使用g ++和優化啓用和更快。但是我試圖優化的實際代碼確實使用了這些選項。謝謝 – user2175966 2013-03-22 19:29:23

0

你說你分配這樣的:

a = new int*[m]; 
for(int i =0; i<m ;i++) a[i] = new int[n]; 

像傑裏Conffin說 - 這不會給你一個連續的記憶塊。 每個新數組(new int[n])將被分配到一個可能完全不同的位置,並且memset只能在連續的塊上工作,因此您必須「手動」重置每個數組。012w順便說一句 - 我敢肯定,你不會去查看在循環中使用memset的任何性能改進(memset本身使用實現使用循環,我認爲)。