Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Desperately seeking the answer to my pointer problem

I have been working on a college C assignment, and have been trying to make sense of a bug I seem to be having with my code. Basically, it seems like something is wrong with my pointers (and or memory allocation).

This assignment is primarily about linked lists, so the structs contain pointers to the next element in the list. Obviously, to traverse the list until I find that the current element has a NULL pointer to the next element (and then I change that to be the pointer to the 'new' element I want to add.

The problem I have though, is for some reason my code seems to be completely screwing with my memory pointers, because they're getting garbled somehow. They seem fine for moment but very soon go rubbish.

Here is what my watches in XCode's debugger are showing me:

My screenshot of the debugger

The first circle shows me the values as the first element in the list, which as far as I can tell are initially set correctly, and should be "C0001\0". The second circle shows the current->nextCategory pointer which should be NULL (0x0) but instead show that weird memory address (look at the size of it!). I assume that these problems are related, but as I am new to C, I don't know how or why.

In either case, when I check current->nextCategory != NULL in my while statement, it throws EXC_BAD_ACCESS:

EXE_BAD_ACCESS error

I've spent the past few hours pulling my hair out becasue I cannot work out what the heck is happening to my program. Am I doing something wrong with my pointers, or using malloc() improperly?

Here is the relevant part of my program:

/****************************************************************************
* Initialises the system to a safe empty state.
****************************************************************************/
void systemInit(GJCType* menu)
{
   if (menu == NULL) {
      fprintf(stderr, "can't initialize system with a null menu pointer.\n");
      exit(EXIT_FAILURE);
   }
   menu->headCategory = NULL;
   menu->numCategories = 0;
}


/****************************************************************************
* Loads all data into the system.
****************************************************************************/
int loadData(GJCType* menu, char* menuFile, char* submenuFile)
{
   FILE *fp;
   size_t len;
   char *line;
   char *buffer;
   CategoryTypePtr category_p;
   ItemTypePtr item_p;
   char *catId;

   if (menu == NULL) 
      return FALSE;

   fp = fopen(menuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", menuFile);
      return FALSE;
    }

   buffer = malloc(MAX_BUFFER_SIZE);
   len = MAX_BUFFER_SIZE;
   catId = malloc(ID_LEN + 1);

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      category_p = malloc(sizeof(CategoryTypePtr));

      if (!tokenizeCategory(line, category_p)) {
         fprintf(stderr, "can't tokenize category:> %s\n", line);
         free(category_p);
         category_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      pushCategory(menu, category_p);
      free(category_p);
      category_p = NULL;
   }

   fp = fopen(submenuFile, "r");
   if(fp == NULL) {
      fprintf(stderr, "can't open %s\n", submenuFile);
      return FALSE;
    }

   while((buffer = fgetln(fp, &len))) {
      line = strtok(buffer, "\n\0");
      item_p = malloc(sizeof(ItemTypePtr));

      if (!tokenizeItem(line, item_p, catId)) {
         fprintf(stderr, "can't tokenize item:> %s\n", line);
         free(item_p);
         item_p = NULL;
         free(buffer);
         free(catId);
         return FALSE;
      }
      category_p = findCategory(menu, catId);
      pushItem(category_p, item_p);
      free(item_p);
      item_p = NULL;
   }

   free(buffer);
   free(catId);
   return TRUE;
}


void pushItem(CategoryTypePtr category, ItemTypePtr item)
{
   ItemTypePtr current;
   ItemTypePtr new;

   if ((new = malloc(sizeof(ItemTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new item pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *item;

   if (category->headItem == NULL) {
      category->headItem = new;
   } else {
      current = category->headItem;
      while (current->nextItem != NULL) {
         current = current->nextItem;
      }
      current->nextItem = new;

   }
   category->numItems++;
}

void pushCategory(GJCType* menu, CategoryTypePtr category)
{
   CategoryTypePtr current;
   CategoryTypePtr new;

   if ((new = malloc(sizeof(CategoryTypePtr))) == NULL) {
      fprintf(stderr, "can't malloc enough memory for new category pointer.\n");
      exit(EXIT_FAILURE);
   }

   *new = *category;

   if (menu->headCategory == NULL) {
      menu->headCategory = new;
   } else {
      current = menu->headCategory;
      while (current->nextCategory != NULL) {
         current = current->nextCategory;
      }
      current->nextCategory = new;
   }
   menu->numCategories++;
}


CategoryTypePtr findCategory(GJCType* menu, char* id)
{ 
   CategoryTypePtr current;

   current = menu->headCategory;
   while (current != NULL) {
      if (!strcmp(current->categoryID, id))
         return current;
      current = current->nextCategory;
   }
   return NULL;
}

/* This function takes the character delimited string and converts it into
 * a category structure at the location of the category pointer supplied.
 */
int tokenizeCategory(char *data, CategoryTypePtr category)
{
   char* buffer;

   if (category == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(category->categoryID, strtok(buffer, "|\n"));
   category->drinkType = *(strtok(NULL, "|\n"));
   strcpy(category->categoryName, strtok(NULL, "|\n"));
   strcpy(category->categoryDescription, strtok(NULL, "|\n"));
   category->numItems = 0;
   category->nextCategory = NULL; 
   category->headItem = NULL; 
   free(buffer);
   return TRUE;
}

/* This function takes the character delimited string and converts it into
 * an item structure at the location of the item pointer supplied.
 */
int tokenizeItem(char *data, ItemTypePtr item, char* categoryId)
{
   char* buffer;
   int i;

   if (item == NULL || strlen(data) < 1)
      return FALSE;

   buffer = malloc(MAX_BUFFER_SIZE);
   strcpy(buffer, data);
   strcpy(item->itemID, strtok(buffer, "|\n"));
   strcpy(categoryId, strtok(NULL, "|\n"));
   strcat(categoryId, "\0");
   strcpy(item->itemName, strtok(NULL, "|\n"));
   for (i = 0; i < NUM_PRICES; i++)
      sscanf(strtok(NULL, "|\n"),"%d.%d",&(item->prices[i].dollars),&(item->prices[i].cents));
   strcpy(item->itemDescription, strtok(NULL, "|\n"));
   item->nextItem = NULL; 
   free(buffer);
   return TRUE;
}

Header definitions:

/* System-wide constants. */
#define ID_LEN 5
#define MIN_NAME_LEN 1
#define MAX_NAME_LEN 25
#define MIN_DESC_LEN 1
#define MAX_DESC_LEN 250
#define NUM_PRICES 3
#define HOT 'H'
#define COLD 'C'
#define FALSE 0
#define TRUE 1
#define MAX_BUFFER_SIZE 1024

typedef struct category* CategoryTypePtr;
typedef struct item* ItemTypePtr;

/* Structure definitions. */
typedef struct price
{
   unsigned dollars;
   unsigned cents;
} PriceType;

typedef struct item
{
   char itemID[ID_LEN + 1];
   char itemName[MAX_NAME_LEN + 1];
   PriceType prices[NUM_PRICES];
   char itemDescription[MAX_DESC_LEN + 1];
   ItemTypePtr nextItem;
} ItemType;

typedef struct category
{
   char categoryID[ID_LEN + 1];
   char categoryName[MAX_NAME_LEN + 1];
   char drinkType;      /* (H)ot or (C)old. */
   char categoryDescription[MAX_DESC_LEN + 1];
   CategoryTypePtr nextCategory;
   ItemTypePtr headItem;
   unsigned numItems;
} CategoryType;

typedef struct gjc
{
   CategoryTypePtr headCategory;
   unsigned numCategories;
} GJCType;
like image 689
Ash Avatar asked May 17 '11 04:05

Ash


1 Answers

It looks to me like you're not allocating memory properly.

category_p = malloc(sizeof(CategoryTypePtr));

This only allocates enough memory to store a single address, not an entire category structure. Try something like:

category_p = malloc(sizeof(CategoryType));
like image 132
sje397 Avatar answered Oct 18 '22 10:10

sje397