Thread: Beginner need help with memory leak....

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    2

    Beginner need help with memory leak....

    Hello,
    I am able to run this without crashing in the "debug" mode in CodeBlocks. But when i run this it sporadicly crashes in "regular" mode. I guess it is something with memory allocation. But I am not sure and I am having problem finding it... Any help would be appreciated.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <math.h>
    #include <time.h>
    #include "queue.h"
    
    
    struct parameters               // struct för parametrarna i kön
    {
        int randomMinItem;
        int randomMaxItem;
        int randomMinCustomers;
        int randomMaxCustomers;
        int itemsPerCycle;
        int amountOfCheckouts;
    };
    
    
    struct queue                    // en struct per kö med pekare mot start och slut på kön
    {
        struct node *head;          // struct pekare
        struct node *tail;          // struct pekare
    };
    
    
    struct node                     // struct node för varje människa i kön med antal varor och pekare till nästa
    {
        int customerItems;
        struct node *next;
    };
    
    
    struct customers                // struct för att hålla koll på statistik
    {
        int customersArrived;
        int customersServed;
        int totalItems;
    };
    
    
    struct parameters *defaultParameters(struct parameters *parameters)      // default parametrar!
    {
        parameters=(struct parameters*)malloc(sizeof(parameters));          // allokerar minne
        parameters->randomMinItem=1;
        parameters->randomMaxItem=10;
        parameters->randomMinCustomers=1;
        parameters->randomMaxCustomers=10;
        parameters->itemsPerCycle=8;
        parameters->amountOfCheckouts=3;
        return parameters;
    }
    
    
    struct queue *createArray(struct parameters *parameters)        // funktion för att skapa arrayen
    {
        struct queue *array=NULL;
        int checkOut;
        int i=0;
        checkOut=parameters->amountOfCheckouts;                     // antal kassor
        array=malloc(sizeof(struct queue)*checkOut);                // Allokerar minne, en kö för varje checkout i parameters
        while(checkOut!=0)                                          // Loopar igenom samtliga köer
        {
            array[i].head=NULL;                                     // varje array gås igenom och får nullvärde på head
            array[i].tail=NULL;                                     // resp tail
            i++;
            checkOut--;                                             // räknar ner checkout
        }
        return array;
    }
    
    
    int setParameters(struct parameters *parameters)                    // Funktion för att ändra parametrar att simulera med
    {
        int input;
        int menubreaker=1;
        do
        {
            system("cls");
            printf("Parameters");
            printf("\n1. Minimum items");
            printf("\n2. Maximum items");
            printf("\n3. Minimum customers");
            printf("\n4. Maximum customers");
            printf("\n5. Amount of checkouts");
            printf("\n6. Items per cycle");
            printf("\n0. Quit");
            printf("\nChoice: ");
            if(scanf("%d", &input)&&input>=0&&input<=6)
            {
                switch(input)
                {
                case 1:
                    printf("Minimum items: ");
                    scanf("%d", &parameters->randomMinItem);
                    break;
    
    
                case 2:
                    printf("Maximum items: ");
                    scanf("%d", &parameters->randomMaxItem);
                    break;
    
    
                case 3:
                    printf("Minimum customers: ");
                    scanf("%d", &parameters->randomMinCustomers);
                    break;
    
    
                case 4:
                    printf("Maximum customers: ");
                    scanf("%d", &parameters->randomMaxCustomers);
                    break;
    
    
                case 5:
                    printf("Amount of checkouts: ");
                    scanf("%d", &parameters->amountOfCheckouts);
                    break;
    
    
                case 6:
                    printf("Items per cycle: ");
                    scanf("%d", &parameters->itemsPerCycle);
                    break;
    
    
                case 0:
                    menubreaker=0;
                    break;
                }
            }
            else
            {
                printf("Error, not a valid choice.");
                printf("\nPress 'Enter' to continue!");
                getch();
            }
        }
        while(menubreaker==1);
        return 0;
    }
    // själva köfunktionen
    struct queue *runSimulation(struct queue *array, struct node *node, struct parameters *parameters, struct customers *customers)
    {
        int minutes;
        int customersInternal=0;
        int tempCustomer=0;
        int range=0;
        int cycleCounter=1;
        customers=(struct customers *)malloc(sizeof(customers));        // Allokerar minne för kunderna.
        node=(struct node *)malloc(sizeof(node));                       // Allokerar minne för kund.
        range=(parameters->randomMaxCustomers-parameters->randomMinCustomers);    // kollar spannet för antal varor
        customers->customersArrived=0;                                  // sätter Arrived resp Served till 0.
        customers->customersServed=0;
        customers->totalItems=0;
    
    
        printf("arrived: %d\n", customers->customersArrived);
        printf("served: %d\n", customers->customersServed);
        printf("items: %d\n", customers->totalItems);
    
    
        printf("How long do you want to run(in minutes)?");
        printf("\nChoice: ");
        scanf("%d", &minutes);
        srand(time(0));
        system("cls");
        while(minutes>0)                                               // Så länge man väljer något över 0
        {
            system("cls");
            printf("\nMinutes: %d", cycleCounter);                         // Varje cykel är "1" minut
            customersInternal=rand()%range+parameters->randomMinCustomers;   // randomizer av antal kunder
            tempCustomer=customers->customersArrived;
            tempCustomer=tempCustomer+customersInternal;                // tempCustomer får värdet för customerArrived + randomizer
            customers->customersArrived=tempCustomer;                   // Läggs i customerArrived(randomtalet för antal varor + customersArrived).
            selectQueue(customersInternal, array, parameters, node, customers);    // välj kö och läggs till i kö
    
    
            //printf("\nNumbers of customers currently in queue: ");
            //traverse(array, node, parameters);          // output folk i kassa
            removeCustomerFromQueue(array, node, parameters, customers);    // ta bort från kö
            //printf("\nNumber of customers after service: ");
            traverse(array, node, parameters);  // mer output om folk i kassakön
            minutes--;      // räknar ner en minut! (cycle)
            cycleCounter++; // räkna cyklerna
        }
        statistics(customers);// statistik
        printf("Press key to continue!");
        getch();
        fflush(stdin);
        int j=0;
            struct node *ptr;
        struct node *del;
        while(j<parameters->amountOfCheckouts)  // loopa igenom samtliga
        {
            ptr=array[j].head;
            while(ptr!=array[j].tail)
            {
                if(array[j].tail!=NULL)
                {
                    del=ptr;
                    ptr=ptr->next;
                    free(del);  // Free
                }
            }
            array[j].head=NULL;                                     // varje array gås igenom och får nullvärde på head
            array[j].tail=NULL;
            j++;
        }
        return array;
    }
    
    
    struct queue *selectQueue(int customersInternal, struct queue *array, struct parameters *parameters, struct node *node, struct customers *customers) // välj kö
    {
        while(customersInternal>0)  // så länge det är över 0
        {
    
    
            array=addCustomerToQueue(array, parameters, node, customers);  // in i AddCustomerToQueue
            customersInternal--;// loopar igenom hela
        }
        return 0;
    }
    
    
    struct queue *addCustomerToQueue(struct queue *array, struct parameters *parameters, struct node *node, struct customers *customers) // lägg till i kö
    {
        int i=0;
        int j;
        int initFlag=0;// vid 0 är kön tom annars är det någon före.
        int range=0;
    
    
        struct node *temp=NULL;                                         // temp structs
        struct node *tempNy=NULL;                                       // temp struct
        range=(parameters->randomMaxItem-parameters->randomMinItem);    // range för varor
    
    
        while(i<parameters->amountOfCheckouts&&initFlag==0)             // så länge i är mindre än kassor och flaggan är 0**Alltså loopar genom alla kassor
        {
            if(array[i].head==NULL)                                     // om arrayplatsens head är noll(kassa tom)
            {
                temp=(struct node *)malloc(sizeof(struct node));        // allokera minne för temp
                if(temp!=NULL)                                          // om ok för allokering
                {
                    // printf("\nCheckout %d: ", i+1);
                    //printf("\nCustomer arrived at checkout %d:\n", i+1);  // kunden kommer fram till kassan
                    temp->next=array[i].head;                               // sparar pekaren head i fältet next
                    temp->customerItems=rand()%range+parameters->randomMinItem; // kundens varor är randomizat
                    // printf("\tCustomer has %d items", temp->customerItems); // kunden har antal varor enligt randomizern
                    customers->totalItems=customers->totalItems+temp->customerItems;
                    array[i].head=temp;                                 // flyttar pekare från temp till head
                    array[i].tail=temp;
                    initFlag=1;                                         // ändrar flagga
                }
            }
            i++;                                                        // plussar i
        }
        if((initFlag==0))               // Vid 0 flagga så
        {
            j=isShortest(array, parameters, node);                  // j får värdet på kortaste kassa
            //printf("\nCheckout %d: ", j+1);
            // printf("\nCustomer arrived at checkout %d.\n", j+1);            // kunden kommer till den kassan
            tempNy=(struct node *)malloc(sizeof(struct node));          // allokera minne
            tempNy->next=array[j].head;                                 // next pekar på huvudet i aktuell kö
            tempNy->customerItems=rand()%range+parameters->randomMinItem;   // antal varor blir randomizat
            // printf("\tCustomer has %d items", tempNy->customerItems);   // kunden har varor
            customers->totalItems=customers->totalItems+tempNy->customerItems;
            array[j].head=tempNy;                                           // arrayens huvud pekar på tempNy
        }
        return array;
    }
    
    
    int isShortest(struct queue *array, struct parameters *parameters, struct node *node) // kortast kö
    {
        int shortest=0;
        int i=0;
        int count=0;
        int baseLine=0;
        int baseLineFlag=0;
        struct node *ptr;
        while(i<parameters->amountOfCheckouts)              // så länge i är mindre än kassor ** loopar genom alla kassor
        {
            //struct node *ptr=array[i].head;                     // ptr pekar på köns huvud
            ptr=array[i].head;                              // ptr pekar på köns huvud
            count=0;
            while(ptr!=array[i].tail)                               // så länge ptrn inte är i slutet
            {
                ptr=ptr->next;                                  // peka på nästa
                count++;                                        // räkna upp
            }
            if(baseLineFlag==0)                             // flaggan är 0
            {
                baseLine=count;                             // baseline blir count
                baseLineFlag=1;                             // ändrar flagga
            }
            if(count<=baseLine)                     // om count är mindre eller samma som baseline
            {
                baseLine=count;                     // så blir baseline count
                shortest=i;                         // kortast = i
            }
            i++;
        }
        return shortest;                            // returnera kortast kö
    }
    
    
    void traverse(struct queue *array, struct node *node, struct parameters *parameters)    // traversera
    {
        int count;
        int j=0;
        int x=0;
        struct node *temp;
        while(j<parameters->amountOfCheckouts)                  // loopa genom alla kassor
        {
            temp=array[j].head;                     // temp blir huvudet på aktuell kassa
            count=0;// räkna från 0
            while(temp!=array[j].tail) // så länge temp inte är i slutet
            {
                temp=temp->next;//frammåt
                count++;//plussa
            }
            if(temp==array[j].tail&&array[j].tail!=NULL)//om sista inte är tom lägg på 1
                count++;
            j++;
            //printf("\nCheckout %d currently have %d customers in queue.", j, count);// output för aktuell kassa j=akteull kassa count=kunder i kassa
            printf("\nCheckout %d: ", j);
            while(count>x)
            {
                printf("*");
                count--;
            }
        }
        //getch();
    }
    // ta bort från kö
    struct queue* removeCustomerFromQueue(struct queue* array,struct node* node,struct parameters* parameters,struct customers* customers)
    {
        int i=0;
        int time;
        while(i<parameters->amountOfCheckouts) // loopa genom alla ksassor
        {
            time=parameters->itemsPerCycle;// tid blir antalet varor som hinns med per cykel (minut)
            while (time>0)                  // så länge det inte är 0
            {
                if(array[i].tail!=NULL)     // om botten inte är tom
                {
                    if((array[i].tail->customerItems-time)<1)   // om köns bottens antal varor minus tid är mindre än 1(finns ingen tid kvar men antal varor är mindre än 1)
                    {
                        time=time-array[i].tail->customerItems; // tid får då tid minus bottens varor
                        array=deleteCustomerFromQueue(array,node,i,customers);  // ta bort kund
                    }
                    else
                    {
                        array[i].tail->customerItems=(array[i].tail->customerItems-time);// antal varor är ursprungsantalvaror - tid
                        time=time-array[i].tail->customerItems;// tid är tid minus bottens antal varor
                    }
                }
                else
                    time=0;// tiden är slut
            }
            i++;// fram i arrayen
        }
        return 0;
    }
    
    
    struct queue *deleteCustomerFromQueue(struct queue *array, struct node *node, int i, struct customers *customers) // ta bort kund
    {
        int tempDelete;
        struct node *temp=array[i].head; // toppen på kön
    
    
        tempDelete=customers->customersServed;
        tempDelete=tempDelete+1;
        customers->customersServed=tempDelete; // för att öka på customerServed
    
    
        while(temp->next!=array[i].tail&&array[i].head!=array[i].tail) //så länge, temps nästa inte är bottem och huvudet inte är botten
        {
            temp=temp->next;// frammåt
        }
        if(temp->next==array[i].tail) //om temps nästa är botten
        {
            free(array[i].tail); // free bottem
            array[i].tail=temp; // botten får då next från förra whilesatsen
        }
        else if(array[i].head==array[i].tail) // annars om topp och botten är samma
        {
            array[i].head=NULL; // nollar båda
            array[i].tail=NULL;
        }
        return array;// returnera arrayen
    }
    
    
    void statistics(struct customers *customers) // statistik
    {
        int queue=0;
        queue=(customers->customersArrived-customers->customersServed);// kö är kvar - hjälpta
        printf("\nTotal customers arrived: %d", customers->customersArrived);//output
        printf("\nTotal customers served: %d", customers->customersServed);//output
        printf("\nCustomers still in queue: %d", queue);// output
        printf("\nTotal items: %d", customers->totalItems);
        printf("\nAverage amount of items: %d", customers->totalItems/customers->customersArrived);
        printf("\n");
    }
    
    
    void terminate(struct queue *array, struct node *node, struct parameters *parameters)
    {
        int j=0;
        struct node *ptr;
        struct node *del;
        while(j<parameters->amountOfCheckouts)  // loopa igenom samtliga
        {
            ptr=array[j].head;
            while(ptr!=array[j].tail)
            {
                if(array[j].tail!=NULL)
                {
                    del=ptr;
                    ptr=ptr->next;
                    free(del);  // Free
                }
            }
            j++;
        }
        free(array);// Free
    }

  2. #2
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    This is not related to the crashing, but you should not use fflush(stdin) or cast the result of malloc.

    Also, using conio.h limits the portability of your code.
    Fact - Beethoven wrote his first symphony in C

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Use an editor and count up your malloc's and free's. They are not equal, and should be. The free Notepad++ is pretty good for this, but I used the browser, just now. Any editor should be able to do this.

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    IIRC, this is wrong; I do not use pointers (or malloc) very often so, you need to confirm it.

    Code:
    parameters=(struct parameters*)malloc(sizeof(parameters));
    The way I think is corrected; notice the star (*) before parameters.
    Code:
    parameters=(struct parameters*)malloc(sizeof(*parameters));
    Note: The cast of "(struct parameters*)" is not recommended in C; required in C++.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  5. #5
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    Continuing with sahta's suggestions, I'd like to elaborate on "recommended" style for your malloc calls:

    Compare this:
    Code:
    parameters=(struct parameters*)malloc(sizeof(*parameters));
    With the (In my opinion) much more readable version:
    Code:
    parameters = malloc( sizeof *parameters );
    Both lines achieve the exact same thing, however the second one is about 20 characters less and much easier to read in my opinion. The important pieces here are the fact that you do NOT need parentheses around VARIABLES with 'sizeof'. However if you are calling sizeof on a type you do have to put parentheses around it (this is because that is the standard syntax for representing an anonymous type, usually used when casting). sizeof is not a FUNCTION it is an OPERATOR. This is an important distinction to remember.

  6. #6
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    nonpuz has the official answer

    c - Do I cast the result of malloc? - Stack Overflow

    Also notice that this solution is more maintanable, because if the type of parameters changes, you will not likely need to change your malloc line.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I note that nonpuz's answer is essentially the same as stahta01's in post #4, except that it has more conviction , does away with the cast in the code rather than noting it in the prose, and is more consistent with the typical style used for operators. That said, I prefer to be consistent in the usage of parentheses with sizeof, so I would write:
    Code:
    parameters = malloc(sizeof(*parameters));
    even though I would also write:
    Code:
    return 0;
    rather than:
    Code:
    return(0);
    hence I am inconsistent with respect to operators, but always use parentheses with sizeof so I get rid of the "important distinction to remember".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    So Laserlight, you're always consistent, in an inconsistent but good, way. :LOL:

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    2
    Thanks for the reply. I am redoing the malloc parts. I did change a part in "deleteCustomersFromQueue"
    Code:
        if(temp->next==array[i].tail) //om temps nästa är botten
        {
          //  free(array[i].tail); // free bottem
           // temptest=array[i].tail;
            array[i].tail=temp; // botten får då next från förra whilesatsen
           // free(temptest);
        }
    It seems to work better after this change but I am still not sure. I am able to run it for some time before it crashes now so I think it is still leaking memory somewhere... I will start to count the frees and the mallocs now...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memory leak
    By rahulsk1947 in forum C Programming
    Replies: 2
    Last Post: 11-11-2007, 01:27 PM
  2. Replies: 2
    Last Post: 09-28-2006, 01:06 PM
  3. Replies: 5
    Last Post: 01-18-2006, 11:02 PM
  4. Is this a memory leak?
    By cboard_member in forum C++ Programming
    Replies: 9
    Last Post: 07-20-2005, 01:15 PM
  5. Memory leak or no?
    By rafe in forum C++ Programming
    Replies: 4
    Last Post: 10-02-2002, 04:33 PM