簡體   English   中英

如何釋放結構中的動態二維數組?

[英]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.

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