Thread: Reallocating Memory

  1. #1
    Registered User
    Join Date
    Mar 2008
    Location
    Staffordshire, UK
    Posts
    2

    Reallocating Memory

    Hi,
    I've been reading posts and using the manual on this site for a while now and its been more than a useful source of information! This time though, I'm completely stumped. My code *almost* seems to work but something goes haywire somewhere.
    Basically, I'm inputting a list of place names and distances between them and then printing them out in a table. I'm using dynamic arrays to store the information so they user can add/remove towns from the list as they require. My initial malloc() works fine and if I edit directly into the file and add/remove places and their corresponding distances then my program still runs exactly as intended.
    It all goes wrong when I try to use realloc() and I try to add a new item to the end of my array.
    I also know some of the code is a bit rough, i'm just a beginner and I havent got around to even attempting to tidy up the code.

    Code:
    int main(void)
    {
    	int i, j, n = 0;
    	char input, rtn[2];
    	char **places;
    	int **distances;
    	FILE *in_file;
    	char line[21];
    	char filename[81];
    	
    	printf("Enter filename containing distance data: \n");
    	gets(filename);
    	
    	in_file = fopen(filename, "r"); //opens file for reading
    	if (in_file == NULL) {
    		printf("Cannot open: %s", filename);
    		return 1; //error
    	}
    	
    	fscanf(in_file, "%d", &n); //Reads in number of places
    	
    	distances = malloc(n * sizeof(int*)); //allocates memory for distance table
    	for(i = 0; i < n; ++i) {
    		distances[i] = malloc(n * sizeof(int));
    	}
    	
    	places = malloc (n * sizeof(int*)); //allocates memory for place names
    	
    	for(i = 0; i < n; ++i) {
    		fscanf(in_file, "%s", line); //reads in place names and places them in array
    		places[i] = malloc (strlen(line)+1);
    		strcpy(places[i], line);
    	}
    
    ....
    Code here to read in distances
    ....
    The above code works fine and allows me to input different size arrays. I also have a display function void display(int **distances, char **places, int n) which runs through the two arrays and prints them out like:
    Click here for an Image at Imageshack showing the output

    What I then call from main() is the follow bit of code which is supposed to reallocate the memory and then add the new data items to the new elements of the array. Then the idea is that I should be able to use all my previous functions, such as display(), from main() on my new set of arrays.

    Code:
    int addPlace(int **distances, char **places, int n) {
    	int i, j;
    	char line[21], rtn, **newPlaces;
    	int *newDist, **newDistances;
    	
    	//Memory required to give the new place a distance to each existing place
    	newDist = (int*)malloc(n * sizeof(int*)); 
    
    	printf("Enter new place name: "); //Enters new place name
    	scanf("%s", line);
    
    	for(i = 0; i < n; ++i) { //Enters the distances from the new place to the existing places
    		printf("Enter distance from %s to %s: ", line, places[i]);
    		scanf("%d%c", &newDist[i], &rtn);
    	}
    
    	++n; //Increases the number of places by one
    
    	//reallocates the memory for the distances so it has one more than before
    	newDistances = realloc(distances, n * sizeof(int*));
    	if ( newDistances == NULL ) {
    		printf("error");
    	}
    	newDistances[n-1] = malloc(n * sizeof(int)); //allocates memory for new set of distances
    	distances = newDistances; 
    	for (i = 0; i < n; ++i) { //Sets the new distances into the distance table
    		distances[n-1][i] = newDist[i];
    		distances[i][n-1] = newDist[i];
    	}
    	distances[n-1][n-1] = 0;
    	
    	//reallocates the memory for the place names so it has one more than before
    	newPlaces = realloc(places, n * sizeof(int*));
    	if ( newPlaces == NULL ) {
    		printf("error");
    	}
    	//allocates memory for new place name and copies over place names
    	newPlaces[n-1] = malloc(strlen(line)+1);
    	places = newPlaces;
    	strcpy(places[n-1], line);
    	
    	return n; //returns new number of places
    }
    But that doesnt work. I get a Segmentation Fault, so I guess i'm overwriting some memory somewhere or going out of bounds of an array or something?

    Hope you can help and sorry for the long winded post, just want to make sure you know whats going on, I see all too many posts on the internet with not enough information in them.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Don't you need at some to point to allocate (n+1)*sizeof(int)?

  3. #3
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    It might seem intimidating but inside the addPlace function the parameters are passed by value, so the pointers you want to reallocate can not be both returned.
    There are two workarounds i can think of.
    The first one involves passing the addresses of the pointers to the function as wa recently discussed, but that will give you something like a:
    Code:
    int addPlace(int ***p_to_distances, char ***p_to_places, int n);
    which itself might be a bit scary, or use a more generic approach and reallocate memory before calling the function. All this mess is because realloc might return a different pointer than the one it was provided with. I would go with the second approach.

    Your code could be rewritten with the reallocation for distances, outside the function like:
    Code:
        ....
        n++;
        distances = realloc(distances, n*sizeof(int *));
        distances[n-1] = malloc(n*sizeof(int));
        places = realloc(places, n*sizeof(char *));
        addPlace(distances, places, n-1);  /* Adjusted so that it adds place at given index */
        ....
    And the places array, is wrongly resized in your code.
    Code:
    	newPlaces = realloc(places, n * sizeof(int*));
    I assume you meant char *.

    Using this approach is probably somewhat cleaner than passing the address of the pointers to the function.
    And finally an approach which i didn't discuss will be to place your arrays in a struct, and use a pointer to the struct as a function parameter. But that approach demands rewriting quite a lot.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  4. #4
    Registered User
    Join Date
    Mar 2008
    Location
    Staffordshire, UK
    Posts
    2
    Thanks for the help.
    Will implement that, i understand why that should work.

    I think i'll go for the second method too, and thanks for the idea about the structs, might go for that at a later date, its only in its early stages at the moment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. available memory from task manager
    By George2 in forum Tech Board
    Replies: 10
    Last Post: 01-18-2008, 02:32 AM
  2. Replies: 4
    Last Post: 01-13-2008, 02:14 AM
  3. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  4. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  5. Shared Memory - shmget questions
    By hendler in forum C Programming
    Replies: 1
    Last Post: 11-29-2005, 02:15 AM