簡體   English   中英

使用memset而不是for循環初始化int **時出現分段錯誤

[英]Segmentation fault on using memset instead of for loops to initialize int**

這是我在c ++中的代碼

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

...現在我正在使用for循環初始化上面的內容,如下所示:

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);

但是我在執行此操作時遇到Segmentation錯誤。 任何人都可以幫我弄清楚我做錯了什么?

int** a;

這只是給你一個對象。 一個int**對象。 它根本不指向任何地方。 沒有要分配的int 當您開始分配int ,就好像它們存在一樣,您會得到未定義的行為。

此外,一個的存儲器布局int**指向的“二維數組” int s是像這樣:在int**在陣列的第一個元素點int* s,並且int* s的點int數組中的第一個元素。 這個內存不是連續的,因為它需要間接跳轉內存,即它不是單個內存塊。 你不能只使用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];
}

但這太丑了!

int** a;

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

“現在我正在使用for循環初始化上面的內容”

您沒有在for循環中初始化它,您只是嘗試將0分配給不存在的元素,這會產生未定義的行為 您需要為這些元素動態分配內存,或者甚至更好:使用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對象被破壞,內存將自動清理)

使用int ** ,通常不會有一個連續的內存塊。 假設你正確使用它,你將有一個指針數組。 然后,每個指針都將分別為其分配一個數組。

在這種情況下,您無法將循環轉換為單個memset (並且仍然可以獲得定義的行為)。

我認為問題在於沒有為實際存儲分配內存。 變量a只是指針(另外沒有初始化)。 它指向的地方?

你說你像這樣分配了它:

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

就像Je​​rry Conffin所說 - 這不會給你一個連續的內存塊。 每個新數組( new int[n] )將分配在一個可能完全不同的位置,memset僅適用於連續的塊,所以你必須“手動”重置每個數組順便說一下 - 我很確定你不是將看到在循環中使用memset的任何性能改進(我認為memset本身使用循環實現)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM