[英]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指針分配一些內存來制作我的數組。
據我所知,這個函數可能只是為了它想要做的事情的次優,但我真正想知道的是:
您通常可以使用變量初始化數組來聲明長度,如:
char trimmed [len];
如果我有一個類型的數組(char trimmed [])它將具有與char(即char *)指針相同的返回類型。
如果我通過分配一些內存並將其分配給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釋放它。
嗯,好吧,回答你的問題:
char * line
內容寫在現有內容之上。 這有效,因為trim()總是只刪除東西。 我認為傳入的緩沖區可以更頻繁地工作,並且養成習慣是一件好事。 至於你的函數,考慮使用memcpy()或它的表兄弟將字節復制進出char緩沖區。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.