[英]Allocation memory error with use struct for c
我寫了一個管理圖書館的代碼。 編譯已經完成,但是在仿真過程中我遇到了Allocation error (case2)
,我不知道為什么。 第一種情況可以正常工作,但是如果我在第一種情況下輸入了多個名稱,則第二種情況不起作用。
我做錯了什么? 我希望我足夠清楚。
typedef struct {
char name[80];
char **books;
int books_num;
} Subscription;
int main() {
// Variables declaration:
int option = 0, subs_num = 0, i = 0, books_num = 0;
Subscription *subs_library;
char **books;
char subs_new_name[80], book_new_name[80];
printf("Choose an option\n");
do {
scanf("%d", &option);
switch (option) {
case 1:
printf("Case 1: enter a new name\n");
scanf("%s", subs_new_name);
if (subs_num == 0) {
subs_library = malloc(sizeof(Subscription));
} else {
subs_library = realloc(subs_library, sizeof(Subscription));
}
strcpy(subs_library[subs_num].name, subs_new_name);
subs_library[subs_num].books_num = 0;
subs_num++;
printf("ADDED\n");
break;
case 2:
printf("Case 2: enter the book name\n");
scanf("%s", book_new_name);
if (books_num == 0) {
books = malloc(sizeof(char*));
books[books_num] = malloc(80 * sizeof(char));
} else {
books = realloc(books, sizeof(char*));
books[books_num] = malloc(80 * sizeof(char));
}
if (books[books_num] == NULL) {
printf("Allocation Error\n");
exit(1);
}
strcpy(books[books_num], book_new_name);
books_num++;
printf("ADDED\n");
break;
}
} while (option != 7);
return 0;
}
我想問題是scanf
只讀取一個字符串,直到出現分隔符為止(在您的情況下,該分隔符是分隔輸入的多個名稱的空格)。 分隔符之后的字符保留在輸入緩沖區中,並由其他對scanf
調用立即處理。
您應該考慮使用getline
讀取名稱並檢查其他對scanf
調用的返回值。
您用於重新分配數組的代碼不正確。 您沒有為新的陣列大小分配足夠的空間。 重新分配這些數組時,將傳遞單個元素的大小,因此該數組的長度仍為1而不是subs_num + 1
。 傳遞給realloc
的大小應為元素數乘以單個元素的大小(以字節為單位)。
將subs_library
和books
初始化為NULL
並更改數組重新分配:
if (subs_num == 0) {
subs_library = malloc(sizeof(Subscription));
} else {
subs_library = realloc(subs_library, sizeof(Subscription));
}
變成這個:
subs_library = realloc(subs_library, (subs_num + 1) * sizeof(*subs_library));
並對books
執行相同的操作,更改:
if (books_num == 0) {
books = malloc(sizeof(char*));
books[books_num] = malloc(80 * sizeof(char));
} else {
books = realloc(books, sizeof(char*));
books[books_num] = malloc(80 * sizeof(char));
}
對此:
books = realloc(books, (books_num + 1) * sizeof(*books));
books[books_num] = malloc(80 * sizeof(char));
或更簡單:
books = realloc(books, (books_num + 1) * sizeof(*books));
books[books_num] = strdup(book_new_name);
重新分配realloc(books, sizeof(char *))
僅分配一個指針char *
的大小,而不分配您需要的擴大數組的大小:
books=realloc(books,sizeof(char*));
您需要將指針( char *
)的大小乘以您計划存儲在數組中的書籍數量。 您可以在books_num
維護書籍books_num
。
正如Joachim Pileborg所說,對於每個分配/重新分配,您都希望它比當前大小多一。 對於第一個分配( malloc()
),您要分配一本書,它是sizeof(char *)
1倍。 這恰好等同於您現有的代碼,這很好。 但是重新分配( realloc()
)每次都以相同的大小重新分配(僅足以容納一個指針),因此您無需擴大分配。 您需要將一個指針所需的大小( sizeof(char *)
)乘以所需的指針數,即books_num + 1
。 正如約阿希姆的回答,這是
books = realloc(books, (books_num + 1)*sizeof(char *));
這將使數組books
的分配再增加一個指針。 然后,在下一行中,正確分配大小為80的字符串。
您的subs_library
具有相同的重新分配問題。
您可能希望減少分配大小的頻率。 在這種情況下,您每次添加條目都將重新分配。 減少重新分配數量的一種簡單技術是,每次分配滿時將分配大小加倍。 但是,您必須保持分配大小(容量),並在添加任何內容時進行檢查。 例如:
char **buffer; /* buffer of pointers to char */
int capacity = 1; /* number of elements allocated for */
int size = 0; /* number of elements actually used */
那么初始分配是
/* Initial allocation */
buffer = malloc(capacity*sizeof(*buffer));
並向buffer
添加一些char *new_item
/* When adding an element */
if ( size == capacity ) {
/* Double allocation every time */
capacity *= 2;
/* Reallocate the buffer to new capacity */
realloc(buffer, capacity*sizeof(*buffer));
}
/* Item will fit, add to buffer */
buffer[size++] = new_item;
請注意,我已經使用sizeof(*buffer)
而不是sizeof(char *)
。 這使編譯器可以確定類型和大小。 這樣,如果由於某種原因更改了buffer
的類型,則不必在代碼中更改更多的位置。 為簡便起見,我省去的另一件事是,您應始終檢查返回值以確保它們不是NULL
。
問題是您的重新分配電話。 例如你
realloc(books,sizeof(char*))
這會將指向books
的內存重新分配為一個指向字符大小的指針,而這正是您已經擁有的大小。 這將導致您索引已分配內存的邊界 ,這是未定義的行為 。
如果你想超過一個元素分配你需要要分配的元素個數,例如乘以基本類型大小
realloc(books, (books_num + 1) * sizeof(char *))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.