Thread: Free memory allocated with malloc outside of the function where it was created

  1. #1
    Registered User
    Join Date
    Oct 2019
    Posts
    3

    Free memory allocated with malloc outside of the function where it was created

    Hello everybody, this is my first time in this kind of forums, I hope to find out the solution to my problem. I have a program which is returning the expected result, but it is using a lot of memory and in some cases reach a high level (120GB), leading to an error. The operative system that I am using is MacOS Mojave 10.14.6 and the IDE is Xcode, I consider myself a beginner, I have been learning C by myself, I will try to summarize my problem, but I suspect this is going to be long...

    First, I have a function called sequences, which takes the Oldseq pointer(this is the first element of a bidimensional array of size nrow times ncol). After some calculations the functions generates a new array with ncol+1 columns and nrow*2 or nrow*4 rows, according with a condition specified at the beginning of the function sequences(). As you can see in the code of sequences(), the pointer Newseq is created with malloc, which means that that memory must be free at some point, but I can not do it inside the function sequences, because Newseq is the pointer that is returning by the function, so I guess I should free that memory after the usage of the function sequences(). Below, you can see the code of the function sequences():
    Code:
    int * sequences(int nrow, int ncol, int * Oldseq,float TransP[NUMSTATES][NUMSTATES], int MinTime[NUMSTATES][NUMSTATES], int s_end, int t_current, int t_end){
        int Nrow=nrow*2;
        if (*(Oldseq)==1) Nrow=nrow*4;
        int Ncol=ncol+1;
        int * Newseq= (int *)malloc(Nrow * Ncol * sizeof(int));
        if (Newseq == NULL)        return NULL;
        for (int i=0; i<Nrow;i++){
            for (int j=0; j<Ncol;j++){
                *(Newseq + i*Ncol + j)=0;
            }
        }
        int pos=0;
        for (int i=0; i<nrow; i++){
            int * newstate=next(*(Oldseq + i *ncol +(ncol-1) ), s_end, t_current, t_end, TransP, MinTime);
            int numopt=0;
            for(int j = 0; j < NUMSTATES; j++){
                if (*(newstate+j)>0) {
                    for (int k=0;k<ncol;k++){
                          *(Newseq + pos*Ncol + k)=*(Oldseq + i *ncol +k);
                    }
                      *(Newseq + pos*Ncol + ncol)=*(newstate+j);
                    pos=pos+1;
                    numopt=numopt+1;
                }//Close if (*(newstate+j)>0)
            }//Close for(int j = 0; j < NUMSTATES; j++)
        }//Close for (int i=0; i<nrow; i++) 
       return Newseq;
    }
    

    Subsequently, I use the function sequences() inside the function allthepaths(). The function allthepaths() initialize a pointer called Allseqs where is going to be saved a bidimensional array created through a for-loop where the function sequences() is used iteratively. Finally, the function allthepaths() returns the pointer Allseqs. The loop goes from t_ini until t_end, the function is returning the proper result, I can see that making t_ini=1 and t_end equal to small values, I can use values event until 50, but the memory is not getting free and when I use several times this function, I reach 120Gb of memory and the program stops. Below, you can see the code of allthepaths().
    Code:
    int * allthepaths(float TransP[NUMSTATES][NUMSTATES], int MinTime[NUMSTATES][NUMSTATES], int s_ini, int s_end, int t_ini, int t_end, int *Nrow, int *Ncol){
        int nrow=1, ncol=1;
        int * Allseqs;
        Allseqs=&s_ini;
        if (t_end<t_ini){
            *(Allseqs + 0*ncol + 0)=0;
            nrow=0;
        }
        if (t_end==t_ini && s_end!=s_ini){
            *(Allseqs + 0*ncol + 0)=0;
            nrow=0;
        }
            for (int time=t_ini;time<t_end;time++){
            Allseqs= sequences(nrow, ncol, Allseqs, TransP, MinTime, s_end, time, t_end);
            int rows=nrow*2;
            if (s_ini==1) rows=nrow*4;
            nrow= countrows(Allseqs, rows, ncol+1);
            ncol=ncol+1;
            Allseqs=(int *)realloc(Allseqs,(nrow * ncol * sizeof(int)));
        }
        changevalues(Nrow, Ncol, nrow, ncol);
        return Allseqs;
    }
    

    As can be seen either in allthepaths()I am allowed to free the memory create with malloc() in the function sequences, what I did was resize the memory using realloc(), which was useful, but it is not enough.
    In the main(), I called the function allthepaths() after the generation of all the parameter required there. At the end I free the memory, but I think I am having still some memory pending to get free. In the next code lines you can see a the part of the man function where I use allthepaths() and where I liberate the memory.
    Code:
    int s_ini=1, s_end=10, t_ini=0, t_end=60;
        int * Allseqs;
        int Nrow, Ncol;
        Allseqs=allthepaths(PROB, MinTraStep, s_ini, s_end, t_ini, t_end, &Nrow, &Ncol);
         for (int i=0; i<Nrow;i++){
            for (int j=0; j<Ncol;j++){
                if (*(Allseqs + i*Ncol + j)>0)
                    printf("%2d\t",*(Allseqs + i*Ncol + j));
            }
            printf("\n");
        }
    free(Allseqs);    
    
    My guess is that the problem is originated because the function sequences() is called inside of a for-loop in allthepaths(), where some memory is created with malloc() and is not getting free properly. I have tried to modify to avoid to use malloc() iteratively, but I have failled. Eventually, I will open other posts, showing the problems that I have had in my other attempts.
    I appreciate the help that all of you could give me.


  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,248
    The problem is that sequences() allocates new memory on each call, but you're overwriting Allseqs with its return value. Therefore, the previous value of Allseqs is lost, resulting in a memory leak on each loop iteration.

    It seems to me that you need two pointers: one points to the previous return value of sequences() (or is a null pointer on the first iteration), and the other points to the current return value of sequences. Hence, in the loop body you would do something like this:
    Code:
    newseqs = sequence(..., oldseqs, ...);
    // blah blah
    free(oldseqs);
    oldseqs = newseqs;
    This way, when the loop terminates, both oldseqs and newseqs would point to the final result, and you would have freed the memory for all the intermediate results.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 12-28-2012, 04:07 PM
  2. Replies: 2
    Last Post: 06-25-2010, 04:04 AM
  3. Can you free memory allocated by a std::string?
    By BrianK in forum C++ Programming
    Replies: 17
    Last Post: 05-15-2008, 11:57 AM
  4. Function to check memory left from malloc and free?
    By Lechx in forum C Programming
    Replies: 4
    Last Post: 04-24-2006, 05:45 AM
  5. Replies: 4
    Last Post: 12-01-2005, 11:16 PM

Tags for this Thread