Search code examples
cdynamic-allocation

Allocation memory error with use struct for c


I wrote a code for managing a library; the compilation is done but during the simulation I obtained an Allocation error (case2) and I don't know why. The first case works correctly but if I entered more than one name in the first case, the second case doesn't work.

What did I do wrong? I hope I was clear enough.

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;
}

Solution

  • Your code to reallocate the arrays is incorrect. You do not allocate enough room for the new array sizes. When you reallocate these arrays, you pass the size of a single element, therefore the array still has a length of 1 instead of subs_num + 1. The size passed to realloc should be the number of elements times the size of a single element in bytes.

    Initialize subs_library and books to NULL and change your array reallocations:

        if (subs_num == 0) {
            subs_library = malloc(sizeof(Subscription));
        } else {
            subs_library = realloc(subs_library, sizeof(Subscription));
        }
    

    Into this:

        subs_library = realloc(subs_library, (subs_num + 1) * sizeof(*subs_library));
    

    And do the same for books, change:

        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));
        }
    

    To this:

        books = realloc(books, (books_num + 1) * sizeof(*books));
        books[books_num] = malloc(80 * sizeof(char));
    

    Or simpler:

        books = realloc(books, (books_num + 1) * sizeof(*books));
        books[books_num] = strdup(book_new_name);