I'm almost finished with this program but the problem I'm having is with freeing the memory I allocated. Particularly in the area where I have pointers to strings.

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

///////////////  user defined data  /////////////////////
struct State
{
	char * name;	// state name
	int year;		// year of entry into the union
	char * cap;		// state capital
	int popRank;	// population ranking
};

struct Database
{
	struct State * list;	// array of states
	int count;				// total count of states
	char * filename;		// input filename
};


///////////////  function prototypes  ////////////////////
struct Database * initDatabase (char * filename);
void deleteDatabase (struct Database * db);
void fillDatabase (struct Database * db);
void insertDatabase (struct Database* db, int index, struct State * state);
void printDatabase (struct Database * db);

int initState (struct State * state, char * name, int year, char * cap, int popRank);
void deleteState (struct State * state);
void copyState (struct State * from, struct State * to);
void printState (struct State * state);



//////////////////////////  program start  ///////////////////////////////////////
int main(void)
{
	struct Database * db;

 	if (db = initDatabase("states.txt"))	// allocate memory for Database struct,
  			 								// then initialize fields of Database struct
	{
		fillDatabase(db);	// read from file
		printDatabase(db);	// print data
		deleteDatabase(db);	// free memory in Database struct
		free(db);			// free Database struct itself

		return 0;
	}
	else  // not successful
	{
	 	 return 1;
   }
}

//////////////////////  Database functions  ////////////////////////////////

//initDatabase - allocates memory for Database struct and initializes 
//               each field
//input: input filename
//return: pointer to Database struct if success
//        NULL if fail
struct Database * initDatabase (char * filename)
{
	FILE * fpIn;
	struct Database * db;
	struct State * states;
	char * string;

	// open input file and check for open success
	if ( ( fpIn = fopen( filename, "r" ) ) )
	{
		// allocate memory for Database struct and check for success
		if ( db = ( struct Database * )malloc( sizeof( struct Database ) ) )
		{
			// allocate memory for filename field and initializes with filename
			if ( string = ( char * )malloc( sizeof( char ) * strlen( filename ) ) )
			{
				strcpy( string, filename );
				db->filename = string;
			}
			else
			{
				printf("Not enough memory!\n");
				exit(0);
			}

			// initialize count field to 50
			db->count = 50;

			// initialize list field by allocating memory for array of 50 states 
			// and check for success
			if ( states = ( struct State * )malloc( sizeof( struct State ) * 50 ) )
			{
				db->list = states;
			}
			else
			{
				printf("Not enough memory!\n");
				exit(0);
			}
		}

	}
	else
	{
		printf("Error with file!\n");
		exit(0);
	}

	// close input file
	fclose( fpIn );

	return db;
}

//deleteDatabase - frees allocated memory inside a Database struct
//input: pointer to Database struct
//return: nothing
void deleteDatabase (struct Database * db)
{
	while ( db->list )
	{
		deleteState( db->list );
		db->list++;
	}
}

//fillDatabase - reads info from file and stores in array of State structs
//input: pointer to Database struct
//return: nothing
void fillDatabase (struct Database * db)
{
   struct State tempState;  // temp State struct to store data from file
   char name[80];	// temp variables
   int year;		// to store
   char cap[80];	// input data
   int popRank;		// from file
   int index = 0;		// index into array of State structs

   FILE *fpIn;
   int cnt;

	// open file from filename field of db
	// don't need to check for file open success because initDatabase already checked
	fpIn = fopen( db->filename, "r" );	

	// loop through all the states
	for ( cnt = 0; cnt < db->count; cnt++ )
	{
	    // read and parse one line of file into 4 input data fields
		if ( fscanf( fpIn, "%[^,], %d, %[^,], %d", name, &year, cap, &popRank ) == 4 )
		{
			// if tempState is created successfully from the 4 input data
			if ( initState (&tempState, name, year, cap, popRank) )
			{	// then copy tempState data into array of states at the current index
				insertDatabase (db, index, &tempState);  
			}
			index++;
		}
		else
		{
			printf("Error reading file!\n");
			exit(0);
		}
	}
 
 	// close file
 	fclose( fpIn );
}

//insertDatabase - copy state data from tempState into appropriate place in array
//input: pointer to Database struct
//       current index in array
//       pointer to tempState containing state data
//return: nothing
void insertDatabase (struct Database * db, int index, struct State * state)
{
   // set pCurrent to location to be inserted in array
	struct State *pCurrent = db->list + index;
	// copy from state to pCurrent
	copyState (state, pCurrent);
	
	return;
}

//printDatabase - print data of state array
//input: pointer to Database struct
//return: nothing
void printDatabase (struct Database * db)
{
	int i;

	printf (" State name      Year     Capital      Pop. rank\n");
	printf ("------------------------------------------------\n");
	for (i = 0; i < db->count; i++)
		printState(db->list+i);
		
	return;
}

////////////////////////  State functions  //////////////////////////////

//initState - initializes a State struct with input data
//input: pointer to State struct
//       name, year, capital, and population rank of state
//return: true for success
//        false for fail
int initState (struct State * state, char * name, int year, char * cap, int popRank)
{
	char * stateName;
	char * capital;
   // if memory allocation is successful, store name
   if ( stateName = ( char * )malloc( sizeof( char ) * strlen( name ) ) )
   {
	   strcpy( stateName, name );
  		state->name = stateName;
   }
   else
   {
	   printf("Not enough memory!\n");
	   return 0;
   }
   
   // store year
   state->year = year;
   
   // if memory allocation is successful, store capital
   if ( capital = ( char * )malloc( sizeof( char ) * strlen( cap ) ) )
   {
	   strcpy( capital, cap );
	   state->cap = capital;
   }
   else
   {
	   printf("Not enough memory!\n");
	   return 0;
   }
   
   // store population ranking
	state->popRank = popRank;

	return 1;
}

//deleteState - frees allocated memory inside a State struct
//input: pointer to State struct
//return: nothing
void deleteState (struct State * state)
{
	free( state->name );
	free( state->cap );
	free( state );
}

//copyState - copies contents between two State structs
//input: pointer to source State struct
//       pointer to destination State struct
//return: nothing
void copyState (struct State * from, struct State * to)
{
	to->name = from->name;
	to->year = from->year;
	to->cap = from->cap;
	to->popRank = from->popRank;
}

//printState - displays State data
//input: pointer to State struct
//return: nothing
void printState (struct State * state)
{
	printf ("%-17s%-8d%-18s%2d\n", state->name, state->year, state->cap, state->popRank);
	
	return;
}

The data from the file is read as state, year, capital, and population ranking.

Can't help much but I'm sure others would greatly appreciate it if you used the tag.[code=c] tag.

I'm almost finished with this program but the problem I'm having is with freeing the memory I allocated. Particularly in the area where I have pointers to strings.

And? What do you want us to do? Read every line of the code and tell you any errors we find?

Tell us any compilation errors. If it compiles, tell us the program output. Then say what you were expecting. Show the lines (or the whereabouts) of where this occurs. In this case, it would also be helpful if you showed us the file you're trying to read.

Can't help much but I'm sure others would greatly appreciate it if you used the [code=c] tag.

He doesn't have to as long as he tells us what is wrong with the code.

Edited 3 Years Ago by pyTony: fixed formating

never mind i figured out the problem(s)

I think I'm having a similar problem. Any chance you could describe how you fixed this problem? Or, what the problem was?

I think I'm having a similar problem. Any chance you could describe how you fixed this problem? Or, what the problem was?

Most memory problems boil down to the program either trying to access/free memory that it didn't allocate (resulting in crashes/segmentation faults), or not freeing memory after the software is finished using it (resulting in memory leaks). Since everyone's code is different, please start a new thread with the exact issue you're experiencing.

This question has already been answered. Start a new discussion instead.