Andrew Hummel
Andrew Hummel

Reputation: 420

Realloc core dumped error in C

I'm trying to familiarize myself with calloc and realloc. I keep getting the below error when the code runs this line:

pb *newPhoneBook = (pb *) realloc(PhoneBook, (10 * sizeof(pb)));

realloc: malloc.c:2842: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
Aborted (core dumped)

Program runs fine up until this particular line. Am I not using the realloc function correctly?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct phonebook {
   char cFirstName[30];
   char cLastName[30];
   char cNumber[30];
} pb;

int entry();
void convert_u(char *);

int main()
{
   int iResponse = 0;

   do {
      printf("\nPhonebook Menu\n****************\n\n");
      printf("1. Enter new contact\n2. Modify existing contact\n3. Exit\n\n");
      printf("Please make selection: ");
      scanf("%d", &iResponse);

      if (iResponse == 1) {
         entry();
      }
      else if (iResponse == 2) {
         //modify();
         printf("\nWorking on it...\n");
      }
   } while (iResponse != 3);

   return 0;
}

int entry()
{
   int x;
   char yes_no[] = "YES";
   pb Book = {'\0', '\0', '\0'};
   pb *PhoneBook = (pb *) calloc(5, sizeof(pb));
   PhoneBook = &Book;

   if (PhoneBook == NULL) {
      printf("\nMemory allocation failed.\n\n");
      return 1;
   }

   for (x = 0; x < 10; x++) {
      if (x > 0) {
         printf("\nAnother entry(yes/no)? ");
         scanf("%s", yes_no);
         convert_u(yes_no);
      }

      if (strcmp(yes_no, "YES") == 0 && x > 0) {
         pb *newPhoneBook = (pb *) realloc(PhoneBook, (10 * sizeof(pb))); //fails here
         if (newPhoneBook == NULL) {
            printf("\nOut of memory!\n\n");
            return 1;
         }
         else {
            PhoneBook = newPhoneBook;
         }
      }
      else if (strcmp(yes_no, "NO") == 0) {
         break;
      }

      printf("\nFirst Name: ");
      scanf("%s", PhoneBook[x].cFirstName);

      printf("\nLast Name: ");
      scanf("%s", PhoneBook[x].cLastName);

      printf("\nPhone Number: ");
      scanf("%s", PhoneBook[x].cNumber);

   }
}

void convert_u(char *yes_no)
{
   int x;

   for (x = 0; x < strlen(yes_no); x++) {
      yes_no[x] = toupper(yes_no[x]);
   }
}

Upvotes: 1

Views: 791

Answers (2)

paxdiablo
paxdiablo

Reputation: 882446

No, you are not using realloc correctly. With regards to your code:

pb Book = {'\0', '\0', '\0'};
pb *PhoneBook = (pb *) calloc(5, sizeof(pb));
PhoneBook = &Book;

While that second line sets PhoneBook to an address in the memory arena (i.e., one that can be passed to realloc), the third line causes it to point at an item outside of the arena.

Calling realloc with that pointer is undefined behaviour.

I'm not entirely certain what your intent is there with that third line. If it's to ensure that the fields are initialised to NUL characters, calloc already does that.

Upvotes: 3

Tom Karzes
Tom Karzes

Reputation: 24102

The problem is here:

pb *PhoneBook = (pb *) calloc(5, sizeof(pb));
PhoneBook = &Book;

You allocate space for 5 pb structs, but then you discard that pointer and instead set PhoneBook to point to Book, which is on the stack. So you aren't even using the result of calloc at that point, and you can't realloc something from the stack.

You could do something like this instead:

pb *PhoneBook = (pb *) calloc(5, sizeof(pb));
PhoneBook[0] = Book;

That will perform a structure copy of Book into the first element of PhoneBook. But if you're going to check if calloc failed, you should do so before the structure copy.

Upvotes: 2

Related Questions