IT_guy
IT_guy

Reputation: 15

Freeing up memory allocated for a very long string (char*) in C?

Please, I need help for freeing up allocated memory for a really long string. I have tried to trim-down the code to this little piece which encompasses the problem I have:

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

#define N 6
#define E 1024

int M[N][N][N], R[N*N][N], C[N*N][N], F[N*N][N];

void init_rcf() {
    int i, j, k, p;

    p = 0;
    for(j=0; j<N; j++) {
        for(k=0; k<N; k++) {
            for(i=0; i<N; i++) 
                R[p][i] = M[i][j][k];
            p++;
        }
    }

    p = 0;
    for(i=0; i<N; i++) {
        for(k=0; k<N; k++) {
            for(j=0; j<N; j++)
                C[p][j] = M[i][j][k];
            p++;
        }
    }

    p = 0;
    for(i=0; i<N; i++) {
        for(j=0; j<N; j++) {
            for(k=0; k<N; k++)
                F[p][k] = M[i][j][k];
            p++;
        }
    }
}

char *bin(int n, int p) {
    int c, d, count;
    char *pointer;
    count = 0;
    pointer = (char*)malloc(p+1);

    for (c = p-1;c >= 0;c--) {
        d = n >> c;
        if (d & 1) 
            *(pointer+count) = 1 + '0';
        else 
            *(pointer+count) = 0 + '0';
        count++;
    }
    *(pointer+count) = '\0';
    return  pointer;
}

int f0(int n) {
    return ceil(log2(n+1)); 
}

int f1() {
    int sum, max = 0;
    for(int k=0;k<N;k++) {
        for(int j=0;j<N;j++) {
            for(int i=0;i<N-1;i++) {
                sum = M[i][j][k] + M[i+1][j][k]; 
                if (sum > max) 
                    max = sum; 
            }
        }   
    }
    return max;
}

int f2() {
    int sum, max = 0;
    for(int k=0;k<N;k++) {
        for(int i=0;i<N;i++) {
            for(int j=0;j<N-1;j++) {
                sum = M[i][j][k] + M[i][j+1][k]; 
                if (sum > max) 
                    max = sum; 
            }
        }   
    }
    return max;
}

int f3() {
    int sum, max = 0;
    for(int j=0;j<N;j++) {
        for(int i=0;i<N;i++) {
            for(int k=0;k<N-1;k++) {
                sum = M[i][j][k] + M[i][j][k+1]; 
                if (sum > max) 
                    max = sum; 
            }
        }   
    }
    return max;
}

int f4() {
    int m1 = f1(),  m2 = f2(), m3 = f3(); 
    if ((m1 >= m2) && (m1 >= m3)) return m1;
    if ((m1 <= m2) && (m2 >= m3)) return m2;
    if ((m1 <= m3) && (m2 <= m3)) return m3;
}

char *g_fxn() {
    char *g = (char *) malloc(1 + (N*N*N)*3); 
    int k = f0(f4());

    init_rcf();
    strcpy(g,"");            
    for(int i=0; i<N*N; i++) 
        for(int j=0; j<N; j++) 
            strcat(g,bin(R[i][j],k));
    for(int i=0; i<N*N; i++) 
        for(int j=0; j<N; j++) 
            strcat(g,bin(C[i][j],k));
    for(int i=0; i<N*N; i++) 
        for(int j=0; j<N; j++) 
            strcat(g,bin(F[i][j],k));
    return g;
}

void convert2bin(char *file_in) {
    const char *FILENAME_IN = file_in;
    const char FILENAME_OUT[] = "temp.txt";
    char c, d; 
    int k=0;

    FILE *infile;
    FILE *outfile;

    infile = fopen(FILENAME_IN, "rb");
    outfile = fopen(FILENAME_OUT, "w");
    if(infile == NULL){
        fprintf(stderr, "Error: Source file not found.\n");
        exit(EXIT_FAILURE);
    }

    while((c = fgetc(infile)) != EOF){
        k++;
        unsigned n = (sizeof(c) * CHAR_BIT) - 1; 
        for (int i=0; i<=n; i++) { 
            int m = (c >> (n-i)) & 1; 
            d = '0'+m;          
            fwrite(&d, 1, sizeof(d), outfile);
        }
    }

    if (k < E) {
        d = '1';
        fwrite(&d, 1, sizeof(d), outfile);
        for (int i=k; i<=E; i++) { 
            d = '0';            
            fwrite(&d, 1, sizeof(d), outfile);
        }
    }

    fclose(infile);
    fclose(outfile);
}

void digest() {
    const char *FILENAME_IN = "temp.txt";
    const char FILENAME_OUT[] = "digest.txt";

    int size = N*N*N; // size of message to construct N*N*N matrix
    char c, msg0[size], *msgf; 

    FILE *infile;
    FILE *outfile;

    infile = fopen(FILENAME_IN, "r");
    outfile = fopen(FILENAME_OUT, "wb");
    if(infile == NULL){
        fprintf(stderr, "Error: Source file \"temp.txt\" not found.\n");
        exit(EXIT_FAILURE);
    }

    int quit = 0;
    while (quit == 0) {
        msgf = (char *) malloc(1 + (size)*3);
        strcpy(msgf, ""); 
        strcpy(msg0, "");
        int p = 0;
        while(((c = fgetc(infile)) != EOF) && (p < size)) {
            msg0[p++] = c;
        }

        if(c == EOF) quit = 1;
        if (p > 0) {
            if (p < size) {
                msg0[p] = '1';
                for(int i=p+1; i<size; i++) 
                    msg0[i] = '0';
            }

            for (int k=0; k<N; k++)
                for (int j=0; j<N; j++)
                    for (int i=0; i<N; i++) {
                        c = msg0[i + N * (j + N * k)];
                        if (c == '0')
                            M[i][j][k] = 0;
                        else 
                            M[i][j][k] = 1;
                    }

            strcpy(msgf, g_fxn());             
            int q = 0;

            while (q<strlen(msgf)) {
                int d;
                char b = 0;
                for (int r=0; r<8; r++) {
                    if (msgf[q++] == '0') 
                        d = 0;
                    else 
                        d = 1;
                    b = ((b<<1) | d);
                }
                fwrite(&b, 1, 1, outfile);
                b = 0;
            }
        }
    }

    free(msgf);
    fclose(infile);
    fclose(outfile);
}

int main(int argc, char *argv[]){
    if (argc!=2) {
        fprintf(stderr, "Error: Provide name of one source file.\n");
        exit(EXIT_FAILURE);
    }

    char *clear_file = argv[1];

    convert2bin(clear_file);

    digest();

    printf("File successfully digested!\n");

    return(0);
}

This code works fine for input files of up to 27 bytes, but beyond that it crashes each time.

After trying to debug I discovered the issue lies on the strcpy(msgf, g_fxn()); call to the function g_fxn and my guess is that problem there comes from the big chunk of memory allocated for the message but which seems not to be liberated after. I'm guessing this because the code works when there are less calls to g_fxn but crashes with more calls.

Anyone has any ideas on how I can fix this?

Upvotes: 0

Views: 131

Answers (3)

ameyCU
ameyCU

Reputation: 16607

There are functions in which memory is allocated but not freed like in -

char *g_fxn() and char *bin(int n, int p)

EDIT

As the pointers are returned in these functions you can use a goto statement.

Well see following example which just shows how to solve your problem -

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

char lol(char c[]);

char lol(char c[])
{ 
  char a[6]="hello";
  char *p=malloc(sizeof(a));
  p=a;
  memcpy(c,p,strlen(a));
  goto DONE;

  DONE:
  free(p);
  return c;
}

int main()
{
   char b[5];
   lol(b);
   printf("%s",b);
  return 0;
}

Upvotes: 1

sth
sth

Reputation: 229744

If a function allocates memory and returns the resulting pointer, not freeing the memory, then the calling function has to make sure that it's freed once it's no longer needed. In your strcpy(msgf, g_fxn()) case this could look like this:

char *tmp = g_fxn();
strcpy(msgf, tmp);
free(tmp);

Generally, each time you get a pointer to memory from malloc() you have to later pass a pointer to that memory to free(), once it's no longer needed.

Upvotes: 0

RhinoDevel
RhinoDevel

Reputation: 712

msgf gets allocated in the while loop of function digest() a lot of times:

msgf = (char *) malloc(1 + (size)*3);

But free() is only called once after the loop:

free(msgf);

This is at least one memory leak I found.

Upvotes: 1

Related Questions