您的主要問題是你正在使用的typedef
名STR
你應該分配和再分配arr[2].word
時,可以使用變量名arr
。
做不是投下malloc
的回報,這是沒有必要的。詳情請參閱:Do I cast the result of malloc?。所有你需要分配的5 STR
數組是:
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
(注:括號是可選的sizeof
,所以它也可以正確地寫入):
STR *arr = malloc (5 * sizeof *arr); /* allocate array of 5 STR */
後聲明STR *arr = malloc (5 * sizeof (*arr))
,你分配word
如下:
arr[2].word = malloc (200 * sizeof *(arr[2].word));
不
STR[2].word = malloc (200 * sizeof *(arr[2].word));
您必須驗證每一個分配。例如: -
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
if (!arr) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
決不realloc
使用指針本身,如果realloc
失敗,你已經失去了指針的原始數據並不能釋放內存。而是使用一個簡單的臨時變量:
void *tmp = realloc (arr[2].word, 400 * sizeof *(arr[2].word));
if (!tmp) {
fprintf (stderr, "error: realloc() virtual memory exhausted.\n");
return 1;
}
arr[2].word = tmp;
在動態分配內存的任何代碼你寫的,你有2名責任關於分配的任何內存塊:(1)始終保持一個指針起始地址對於內存塊來說,(2)當它不再需要時,它可以是釋放。養成跟蹤和釋放你分配的所有內存的習慣,而不是依靠退出來完成它。當您開始編寫更復雜的代碼來分配代碼中的函數內存時,這將帶來收益。在這種情況下,你將需要:
free (arr[2].word); /* free allocated memory */
free (arr);
把這些作品放在一起,你可以這樣做:
typedef struct {
char *word;
} STR;
int main (void)
{
STR *arr = malloc (5 * sizeof (*arr)); /* allocate array of 5 STR */
if (!arr) { /* validate allocation */
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
/* allocate/validate arr[2].word */
if (!(arr[2].word = malloc (200 * sizeof *(arr[2].word)))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1; /* or handle error as appropriate */
}
/* realloc/validate using temporary variable */
void *tmp = realloc (arr[2].word, 400 * sizeof *(arr[2].word));
if (!tmp) {
fprintf (stderr, "error: realloc() virtual memory exhausted.\n");
return 1;
}
arr[2].word = tmp;
free (arr[2].word); /* free allocated memory */
free (arr);
return 0;
}
示例使用/ Valgrind的輸出
這是你必須使用一個內存錯誤檢查程序,以確保您沒有超出/超出您分配的內存塊,嘗試讀取或基於未初始化的值進行跳轉,最後確認您已釋放所有已分配的內存。
對於Linux valgrind
是正常的選擇。有許多微妙的方法來濫用指針或新的內存塊。使用內存錯誤檢查器可以識別任何問題並驗證您分配的內存的正確使用情況,而不是通過segfault
發現問題。每個平臺都有類似的內存檢查器。它們都很簡單,只需通過它運行你的程序。
例如,編譯代碼並保存可執行文件./bin/alloc
,那麼您需要做的基本使用valgrind
簡單地用你的程序作爲第一個參數運行valgrind
:
$ valgrind ./bin/alloc
==8949== Memcheck, a memory error detector
==8949== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==8949== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==8949== Command: ./bin/alloc
==8949==
==8949==
==8949== HEAP SUMMARY:
==8949== in use at exit: 0 bytes in 0 blocks
==8949== total heap usage: 3 allocs, 3 frees, 640 bytes allocated
==8949==
==8949== All heap blocks were freed -- no leaks are possible
==8949==
==8949== For counts of detected and suppressed errors, rerun with: -v
==8949== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
務必確認所有堆塊被釋放 - 沒有泄漏是可能的和同樣重要的錯誤摘要:0錯誤從0上下文。 (注意:某些操作系統不提供足夠的內存排除文件(排除系統和操作系統內存被報告爲正在使用),這將導致valgrind
報告某些內存尚未釋放,儘管您已完成你的工作,並釋放所有塊,你分配,並在你的控制下。)
看看它,讓我知道你是否有任何問題。
(注:C有利於小寫的名稱,保留全部大寫的常量和宏這只是風格,所以它是由你)
'STR [2]'應該是'ARR [2 ]',但只有在您確認第一個'malloc'調用成功後。另外,在'malloc'調用上丟失 - 它們是不必要的,根據C89標準可以掩蓋一個錯誤。 –
你錯過了'realloc'的第一個參數。 –