Search code examples
cpointersstructmalloccoredump

Getting core dumps when free() is used


I'm doing a school assignment and the driver was given to me along with the header file. My job is to complete the functions that read data from a text file and then search it for a name and return the email address. It's a huge exercise in using pointers and structures.

The program reads in a text file of names and email addresses then dynamically creates a structure array using malloc(). The struct Card is built of two char pointers and I find the length of the data using strlen(), malloc() memory for that size and assign the struct to the memory address given.

It all seems to work fine until the end after it has printed the name and email and is about to free() the memory. I get an Aborted (core dump) message every time. Don't know what the issue could be.

I've placed a printf() just before the free() to try and track down where the issue is but it appears to be happening either during the name/email printout or just after it happens because my printf() test point that is one line before the free() is never executed.

I'm assuming the driver program is okay and it has something to do with my functions. Anyone care to take a stab at it?

    //Main
    #include <stdio.h>
    #include <stdlib.h>
    #include "lab9utils.h"

    int main(int argc, char * argv[]) {

        // Variable declarations.
        struct Card * cards;
        int size;
        int k;
        char * email;

        // Make sure we have 2 extra command-line paramgers.
        if (argc < 3) {
            printf("Usage:  ./lab9.exe <data_filename> <name_to_lookup>");
            return 0;
        }

        // Get the cards and do the lookup.
        cards = getCards(argv[1], &size);
        email = lookup(cards, argv[2], size);

        // Display the output message ("sorry!" or "name -> email").
        if (email == NULL) {
            printf("Sorry, that name was not in the list of cards.\n");
        } else {
            printf("%s -> %s\n", argv[2], email);
        }

        // Free the memory used by the structures.
        k = 0;
        printf("Test Point#1");
        for (k = 0; k < size; k++) {
            free(cards[k].name);
            free(cards[k].email);
        }
        printf("Test Point#2");
        free(cards);

        return 0;
    }





  // Header

    #ifndef LAB9UTILS_H
    #define LAB9UTILS_H

    struct Card {
        char * name;
        char * email;
    };

    struct Card * getCards(char * filename, int * size);
    char * lookup(struct Card * cards, char * name, int size);

    #endif


   //  Functions

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

    struct Card * getCards(char * filename, int * size_return) {

        int i,size;
        char cTempName[51]={0};
        char cTempEmail[51]={0};

        size = 0;

        //  I/O Setup   
        FILE *fp; 
        fp = fopen(filename,"r");

        //  error checking
        if(fp == NULL)
        {
            perror("Error in opening file");
            return(NULL);
        }

    //  Input Loop      

        while(!feof(fp))
        {
            fscanf(fp,"%s%s",cTempName,cTempEmail);

            size++;
        }   

        size=size-1;

        fclose(fp);

        struct Card * card = (struct Card *)malloc(*size_return * sizeof(struct Card));

        fp = fopen( filename ,"r");

        //  error checking
        if(fp == NULL)
        {
            perror("Error in opening file");
            return(NULL);
        }

        for(i=0;i<size;i++)
            {
                fscanf(fp,"%s%s",cTempName,cTempEmail);
                card[i].name=(char *)malloc((strlen(cTempName)+1));
                card[i].email=(char *)malloc((strlen(cTempEmail)+1));
                strcpy(card[i].name,cTempName);
                strcpy(card[i].email,cTempEmail);

            }

        fclose(fp); 
        //  loop to confirm data was read
        for(i=0;i<size;i++)
                {
                    printf("[ %d ] Name:%s email:%s  Total size:%d\n",i,card[i].name,card[i].email,size);
                }

        *size_return = size;        

        return card;

    }

    char * lookup(struct Card * cards, char * name, int size) {

        int i;

        for(i=0;i<size;i++)
            {
                if (strcmp(cards[i].name,name)==0) 
                {
                    return cards[i].email;
                }
            }

            return NULL;

    }

Solution

  • The value of *size_return is garbage, because you are setting it to size only at the end of the function.

    Change this:

    struct Card * card = (struct Card *)malloc(*size_return * sizeof(struct Card));
    

    To this:

    struct Card * card = (struct Card *)malloc(size * sizeof(struct Card));