[英]how to double array size (error on second time)
這里有一些幫助,試圖在 cpp 中加倍數組
在第二次調整大小時我得到了這個(混亂的輸出)
% ./sample
[5] 1 2 3 4 5
[20] 1 2 3 4 0 6 7 -1610612736 1 2 3 4 14 0 0 0 0 -1610612736 0 0
同樣刪除內存集(將剩余位置歸零)
#include <iostream>
#include <cstdlib>
using namespace std;
void resize(int* v, int* size){ // double the array size
int newSize = (*size) * 2;
v = (int *) realloc(v, (size_t) newSize);
memset(v+(*size), 0, sizeof(int) * (newSize - *size) );
*size = newSize;
}
int main(){
int size = 5;
int* v = new(nothrow) int[size]();
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
resize(v, &size);
resize(v, &size); // <- messy output
v[5] = 6; v[6] = 7;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
return 0;
}
謝謝您的幫助,
將malloc()
與realloc()
或new
和delete[]
一起使用 - 不能同時使用
您的直接問題是您將指針傳遞給 function 並且 function 收到一個副本 - 因此對 function 中的v
所做的任何更改都會對指針的本地副本進行(它有自己的地址並且與指針v
非常不同在main()
)
另一個問題是混合使用new
和realloc()
,這會導致未定義的行為。 在main()
中使用malloc()
) 或使用new
在您的 function 中手動創建和復制,並在分配新塊之前在原始對象上調用delete[]
。
由於這是 C++,您可以通過將指針引用傳遞給 function(例如int*& v
)來輕松解決問題,因此realloc()
對原始指針地址而不是副本進行操作。
注意:正如 JL 在評論中提到的,每當您調用realloc()
時,您必須將結果分配給一個臨時指針,您在分配給原始指針之前驗證realloc()
是否成功。 當(不是如果) realloc()
失敗時,它將返回NULL
並用 NULL 覆蓋您的原始指針,從而使NULL
的塊無法釋放,從而造成 memory 泄漏。
要將臨時指針與realloc()
一起使用,您可以這樣做:
void resize(int*& v, int *size){ // double the array size
int newSize = (*size) * 2;
/* always realloc with temporary pointer so if realloc fails
* you don't overwrite your orignal pointer with NULL creating
* a memory leak.
*/
int *tmp = (int *)realloc (v, (size_t) newSize * sizeof *v);
if (!tmp) { /* validate every allocation */
perror ("realloc-v");
return;
}
v = tmp; /* successful realloc(), assign tmp to v */
memset (v+(*size), 0, sizeof(int) * *size );
*size = newSize;
}
此外,在main()
中要使用realloc()
,您最初必須使用malloc()
(或calloc()
或realloc()
,但不是new
)進行分配。 此外,保護您的循環范圍,或者如果您不打算使用{...}
保護 scope,那么至少適當縮進以便您的意圖明確,例如
int main(){
int size = 5;
int *v = (int*)malloc(size * sizeof *v);
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << endl;
resize(v, &size);
resize(v, &size);
if (size > 6) { /* validate size / protect memory bounds */
v[5] = 6;
v[6] = 7;
}
cout << "[" << size << "] ";
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << endl;
return 0;
}
(您還應該為memset()
添加#include <cstring>
)
使用new
和delete[]
如果您使用new
在 function 中創建一個大小加倍的新塊,則可以將分配保留在main()
中,將值復制到新塊(並將 rest 初始化為0
)並在原始塊上調用delete[]
在將新塊分配給原始指針之前阻塞。
在那種情況下,你會做類似的事情:
void resize(int*& v, int *size){ // double the array size
int newSize = (*size) * 2;
/* create a new block of newSize */
int *tmp = new(nothrow) int[newSize]();
/* copy/initialize */
for (int i = 0; i < newSize; i++) {
if (i < *size)
tmp[i] = v[i];
else
tmp[i] = 0;
}
delete[] v; /* free original block */
v = tmp; /* assign tmp to v */
*size = newSize;
}
示例使用/輸出
在任一情況下( malloc()
、 realloc()
)或( new
、 delete[]
),結果都是相同的:
$ ./bin/realloc_arr
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0
在這兩種情況下,您都需要驗證您的 memory 使用valgrind
或類似的 memory 使用/錯誤檢查您的操作系統。 您需要在main()
的末尾添加free(v)
或delete[] v
來處理釋放您為 memory 檢查目的分配的所有 883933302533388(它將在程序退出后釋放,但沒有明確說明在main()
中釋放它仍然會在程序退出時顯示為正在使用。
要使用 valgrind,只需通過它運行您的程序。 進行上述更改后,您將擁有:
$ valgrind ./bin/realloc_arr
==22674== Memcheck, a memory error detector
==22674== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22674== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22674== Command: ./bin/realloc_arr
==22674==
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0
==22674==
==22674== HEAP SUMMARY:
==22674== in use at exit: 0 bytes in 0 blocks
==22674== total heap usage: 5 allocs, 5 frees, 73,868 bytes allocated
==22674==
==22674== All heap blocks were freed -- no leaks are possible
==22674==
==22674== For counts of detected and suppressed errors, rerun with: -v
==22674== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始終確保釋放所有塊並且沒有 memory 錯誤。
供參考工作版本
#include <iostream>
using namespace std;
void resize(int*& v, int* size){ // double the array size
int newSize = (*size) * 2;
int* tmp = new(nothrow) int[newSize](); // zeroing on the next line is redundant?
for(int i = 0; i < newSize; i++) tmp[i] = (i < *size) ? v[i] : 0;
delete[] v;
v = tmp;
*size = newSize;
}
int main(){
int size = 5;
int* v = new(nothrow) int[size]();
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
resize(v, &size);
resize(v, &size); // <- NOW, working output
//resize(v, &size);
v[5] = 6; v[6] = 7;
cout << "[" << size << "] ";
for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.