[英]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];
其中N
和M
是常量表達式。 這是連續存儲的,但我仍然不建議使用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]
這將有更多的優勢:
vector
對象被破壞,內存將自動清理) 使用int **
,通常不會有一個連續的內存塊。 假設你正確使用它,你將有一個指針數組。 然后,每個指針都將分別為其分配一個數組。
在這種情況下,您無法將循環轉換為單個memset
(並且仍然可以獲得定義的行為)。
我認為問題在於沒有為實際存儲分配內存。 變量a只是指針(另外沒有初始化)。 它指向的地方?
你說你像這樣分配了它:
a = new int*[m];
for(int i =0; i<m ;i++) a[i] = new int[n];
就像Jerry Conffin所說 - 這不會給你一個連續的內存塊。 每個新數組( new int[n]
)將分配在一個可能完全不同的位置,memset僅適用於連續的塊,所以你必須“手動”重置每個數組順便說一下 - 我很確定你不是將看到在循環中使用memset的任何性能改進(我認為memset本身使用循環實現)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.