简体   繁体   中英

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?

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.

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;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM