[英]How to free dynamic 2d array that's in a struct?
我在這個結構中有一個動態的2d數組:
struct mystruct{
int mySize;
int **networkRep;
};
在我的代碼塊中,我使用它如下:
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
這就是我聲明2d數組的方式:
int** declareMatrix(int **mymatrix, int rows, int columns)
{
mymatrix = (int**) malloc(rows*sizeof(int*));
if (mymatrix==NULL)
printf("Error allocating memory!\n");
int i,j;
for (i = 0; i < rows; i++)
mymatrix[i] = (int*) malloc(columns*sizeof(int));
for(i=0; i<rows; i++){
for(j=0; j<columns; j++){
mymatrix[i][j] = 0;
}
}
return mymatrix;
}
這就是我釋放2d數組的方式:
void freeMatrix(int **matrix, int rows)
{
int i;
for (i = 0; i < rows; i++){
free(matrix[i]);
}
free(matrix);
matrix = NULL;
}
我所看到的奇怪的行為是,當我編譯並運行我的程序時,一切看起來都不錯。 但是當我將stdout傳輸到txt文件時,我遇到了一個seg錯誤。 但是,如果我注釋掉包含“freeMatrix”調用的循環,則不會發生seg錯誤。 我究竟做錯了什么?
我沒有在免費代碼中看到任何問題,除了, freeMatrix
被調用100
次,而你的分配只有1
。
所以,要么分配如下:
for(int i=0; i<100; i++) //Notice looping over 100 elements.
astruct[i].networkRep = declareMatrix(astruct[i].networkRep, 200, 200);
或者,只為您在原始代碼中分配的第0個元素免費。
freeMatrix(astruct[0].networkRep, 200);
旁注:初始化您的astruct
array
。
mystruct astruct[100] = {};
struct myStruct astruct[100];
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
// do stuff...
int i;
for(i=0; i<100; i++)
freeMatrix(astruct[i].networkRep, 200);
你分配了一個astruct但是釋放了100個; 如果任何99個額外的不是NULL,那么會崩潰,這可能在你進行重定向時發生。 (由於astruct在堆棧中,它將包含那里留下的任何內容。)
其他事宜:
您使用的是數字文字而不是清單常量...定義NUMROWS和NUMCOLS並一致地使用它們。
擺脫declareMatrix的第一個參數...你傳遞一個值但從不使用它。
在freeMatrix中,
matrix = NULL;
什么也沒做。 啟用優化后,編譯器甚至不會生成任何代碼。
if (mymatrix==NULL)
printf("Error allocating memory!\n");
您應該在出錯時退出(1),否則您的程序將崩潰,您甚至可能看不到錯誤消息,因為a)stdout被緩沖並且b)您將其重定向到文件。 這也是將錯誤消息寫入stderr而不是stdout的原因。
astruct[0].networkRep = declareMatrix(astruct[0].networkRep, 200, 200);
你沒有傳遞指針的地址。 它只是將內存中的值傳遞給不需要的函數。
你唯一初始化struct的第一個變量,但是當你試圖釋放內存時,你正在分配尚未分配的內存(astruct [1],依此類推,直到100)。
當您使用malloc時,它實際上分配的內存比您指定的多一點。 額外內存用於存儲諸如塊大小之類的信息,以及指向下一個空閑/已使用塊的鏈接,有時還有一些保護數據可幫助系統檢測是否寫入了已分配塊的末尾。
如果傳入不同的地址,它將訪問包含垃圾的內存,因此其行為未定義(但最常見的是導致崩潰)
索引和計數無符號整數類型就足夠了。 size_t
是這種選擇的類型,因為它保證足夠大以解決/索引目標機器上的內存/數組元素的每個字節。
struct mystruct
{
size_t mySize;
int ** networkRep;
};
始終正確初始化變量:
struct myStruct astruct[100] = {0};
分配器的幾個問題:
size_t
作為計數器和指示和大小(“行”,“列”)(為什么請參見上文)。 malloc()
返回的值,因為在C中沒有必要,不推薦使用 perror()
來記錄錯誤,因為它從操作系統中獲得了關於as possibe的最多信息。 有可能做到這一點:
int declareMatrix(int *** pmymatrix, size_t rows, size_t columns)
{
int result = 0; /* Be optimistc. */
assert(NULL != pmatrix);
*pmymatrix = malloc(rows * sizeof(**pmymatrix));
if (NULL == *pmymatrix)
{
perror("malloc() failed");
result = -1;
goto lblExit;
}
{
size_t i, j;
for (i = 0; i < rows; i++)
{
(*pmymatrix)[i] = malloc(columns * sizeof(***pmymatrix));
if (NULL == (*pmymatrix)[i])
{
perror("malloc() failed");
freeMatrix(pmymatrix); /* Clean up. */
result = -1;
goto lblExit;
}
for(i = 0; i < rows; ++i)
{
for(j = 0; j < columns; ++j)
{
(*pmymatrix)[i][j] = 0;
}
}
}
}
lblExit:
return 0;
}
解除分配器的兩個問題:
有可能做到這一點:
void freeMatrix(int *** pmatrix, size_t rows)
{
if (NULL != pmatrix)
{
if (NULL != *pmatrix)
{
size_t i;
for (i = 0; i < rows; ++i)
{
free((*pmatrix)[i]);
}
}
free(*pmatrix);
*pmatrix = NULL;
}
}
然后使用這樣的東西:
struct myStruct astruct[100] = {0};
...
int result = declareMatrix(&astruct[0].networkRep, 200, 200);
if (0 != result)
{
fprintf("declareMatrix() failed.\n");
}
else
{
// Note: Arriving here has only the 1st element of astruct initialised! */
// do stuff...
}
{
size_t i;
for(i = 0; i < 100; ++i)
{
freeMatrix(&astruct[i].networkRep, 200);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.