簡體   English   中英

我的課程對我的作業來說足夠好,但我知道它不好

[英]My program is good enough for my assignment but I know its not good

我剛剛開始為uni工作,它為我提出了一個問題。

我不明白如何在沒有內存泄漏的情況下從函數返回字符串。

char* trim(char* line)  {
    int start = 0;
 int end = strlen(line) - 1;

 /* find the start position of the string */
 while(isspace(line[start]) != 0)  {
     start++;
 }
 //printf("start is %d\n", start);

 /* find the position end of the string */
 while(isspace(line[end]) != 0)  {
     end--;
 }
 //printf("end is %d\n", end);

 /* calculate string length and add 1 for the sentinel */
 int len = end - start + 2;

 /* initialise char array to len and read in characters */
 int i;
 char* trimmed = calloc(sizeof(char), len);

 for(i = 0; i < (len - 1); i++)  {
     trimmed[i] = line[start + i];
 }
 trimmed[len - 1] = '\0';

    return trimmed;
}

正如你所看到的,我正在返回一個指向char的指針,這是一個數組。 我發現如果我試圖通過以下方式制作'修剪'數組:

char trimmed[len];

然后編譯器會拋出一條消息,說明在這一行上預期有一個常量。 我認為這意味着由於某種原因,在初始化數組時你不能使用變量作為數組長度,盡管有些東西告訴我這不可能是正確的。

所以我通過為char指針分配一些內存來制作我的數組。

據我所知,這個函數可能只是為了它想要做的事情的次優,但我真正想知道的是:

  1. 您通常可以使用變量初始化數組來聲明長度,如:

    char trimmed [len];

  2. 如果我有一個類型的數組(char trimmed [])它將具有與char(即char *)指針相同的返回類型。

  3. 如果我通過分配一些內存並將其分配給char指針來創建我的數組,我該如何釋放這個內存。 在我看來,一旦我返回這個數組,我無法訪問它以釋放它,因為它是一個局部變量。

解決(3) - 完成后,您可以從調用代碼中free新分配的字符串:

char* tmp = trim(myline);

if (tmp != NULL) {
    ....
    free( tmp );
}

但是這會給調用者帶來負擔,以便記住釋放內存。 因此,您可以考慮將已分配的緩沖區和緩沖區大小傳遞給trim() ,例如:

void trim(char* line, char *trimmed_buf, int trimmed_buf_len){ ... }

尼爾在解決你的其他問題方面表現出色。 基本上是一個數組聲明char trimmed[len]; 將在堆棧上聲明一個局部變量,因此雖然在語法上將char *返回到此內存是正確的,但它指向的內存位置將不再有效。

要回答您的具體問題,請使用以下語法:

char trimmed[len];

其中len是一個變量,只允許在C99中,而不是在C89或C ++中。 返回類型確實是一個char * ,但返回trimmed的局部變量會導致未定義的行為,所以不要這樣做。 如果你通過calloc動態地在一個函數中分配一個數組並返回它,那么使用函數返回的指針由函數的調用者來釋放它。

關於動態調整大小的數組聲明,如char trimmed[len]; 最新版本的C標准( ISO / IEC 9899:1999 )允許這樣做,但對於這個功能它根本沒有幫助。 trimmed變量的范圍在trim函數中,並在堆棧中分配。 所以,如果你把return trimmed; 在你的代碼中,你返回一個指向堆棧變量的指針,這個變量所在的堆棧部分將在函數返回的位置釋放,這樣就不會很好了......

讓調用者傳入指向函數的內存區域(最大長度)的指針。 這樣調用者將負責分配(和釋放)內存,並且該函數僅提供約束傳遞給函數的緩沖區的輸出。

當然,使用該功能的人仍然可以解決問題(通過指定與實際緩沖區大小無關的長度,但是你可以正確地說它是調用者的錯誤,而不是這個函數錯誤。

除了像使用std::string這樣的C ++解決方案之外,您總是可以分配一個設置大小的數組,並將大小作為參數傳遞,並將數組作為參數傳遞或作為指針?

這樣,數據在相同的范圍內分配,並且沒有內存泄漏。

然后你可以在打電話后隨時釋放內存。 這意味着負責創建它的代碼和負責銷毀數據的代碼是不一樣的,這可能是錯誤和錯誤的前兆。

功能外的分配和刪除:

使用char trimmed [SIZE]從堆棧中分配它並將其傳遞給函數或使用calloc從堆傳遞並將其傳遞給函數。

函數內部的分配和外部的刪除:

您使用calloc在函數內部分配它,但調用者必須使用free釋放它。

嗯,好吧,回答你的問題:

  1. 是的,數組將在堆棧上分配,而不是堆,並在函數返回時釋放。
  2. 是的,char []大部分相當於char *。 由於存在語義差異,最好將它們分開。
  3. 使用任何指向內存的指針,您可以免費使用。 在您的情況下,您將釋放返回該功能。 這被認為是非常糟糕的形式和容易出錯的。 你通常希望allocat'er成為free()呃。 或許,您可以傳入新空間的緩沖區,或者函數的調用者可以同意將char * line內容寫在現有內容之上。 這有效,因為trim()總是只刪除東西。 我認為傳入的緩沖區可以更頻繁地工作,並且養成習慣是一件好事。

至於你的函數,考慮使用memcpy()或它的表兄弟將字節復制進出char緩沖區。

暫無
暫無

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

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