2011-09-10 3 views
0

すべて
私はCプログラムに問題があり、グーグルで解決することができませんでした。
Cファイルが下にあり、再帰関数からの復帰時に動的にメモリを解放できないという問題がありました。

プログラムは整数の階乗を数字のストリングの形式で計算し、
は各乗算を実行し、同じ方法で結果を表示します(数字のストリング)。
これは、設計された仕事を実行し、あなたがより良い方法を使用すると確信しています。
私の問題は、割り当てられたメモリの一部を解放できないという事実だけです。成長し、結果の文字列に対応するために()をreallocのための呼び出し - (malloc関数)
各「乗算」の - - 私が行うために使用文字列「1 N」

犯人は、割り当ての2種類があります。
再帰
時に割り当てられた各ポインタをコピーして、「事実から戻ったときにそれらを解放するために、グローバル* PNTを使用して問題を解決するため、私はそこにすべての休憩明らかに、再帰中にそれらを解放しようとするので、私は
にしようとした場合() ';これは、前もって
の最終的な階乗の桁数を計算し、それを使って
'
* pnt'と 'realloc()'の両方にメモリを割り当てる場合にのみ機能しますと呼ばれる。 'free()'はヒープ上のいくつかのポインタを見つけることができないので、 'realloc()'の呼び出しは、
のクラッシュを引き起こします。
私は、回帰関数とグローバルが混在しないことを知っています。 何人かのエキスパートが、私がやろうとしていることを実行することが可能かどうか教えてもらえますか?
私は適切なプログラマーではなく、ちょっとしたCを学ぼうとしています。私は
非再帰的なコードを使って同じ仕事をすることができますが、私はこのようにこの回を試してみたかったのです。 ありがとう、マリアン。再帰関数からの復帰時に動的に割り当てられたメモリを解放する方法

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

#ifdef DMALLOC 
#include <dmalloc.h> 
#endif 

char *fact(char *n, int *sz); 
char *mulstr(char *st1, char *st2, int *s); 
char *subone(char *sb); 
char *reverse(char *rv); 

/* ************************************************************************ */ 
int main(int argc, char **argv) { 
    int l = 0; 
    if(argc < 2 || !isdigit(*argv[1])) 
    puts("\a\nWe need a number."); 
    else { 
    int num = atoi(argv[1]); 
    for(;;) { 
     if(!*argv[1]) { 
     puts("\n<Enter> another number."); 
     scanf("%d", &num); 
     if(num < 0) 
      return 0; 
     while(getchar() != '\n'); 
     } 
     system("clear"); 
     int s = 16; /* The size whic will grow to the eventual length of n1!. */ 
     char *n1 = malloc(s); 
     sprintf(n1, "%d", num); 
     n1 = fact(n1, &s); 
     l = strlen(n1); 
     printf("%d! = %s\nused %d bytes\nis %d digits long.\n", num, n1, s, l); 
     free(n1); 
     argv[1] = ""; 
    } 
    } 
    return 0; 
} 

/* Recursively computes N! in the for of string f. */ 
/* ************************************************************************ */ 
char *fact(char *f, int *s) { 
    if(!strcmp(f, "1") || !strcmp(f, "0")) 
    strcpy(f, "1"); 
    else { 
    char *mone = malloc(strlen(f) + *s + 1000); 
    if(!mone) { 
     perror("Allocation mone"); 
     exit(1); 
    } 
    strcpy(mone, f); 
    mone = subone(mone); 
    if(f && *f && mone && *mone) 
     f = mulstr(f, fact(mone, s), s); 
    else { 
     printf("ERROR\a empty string.\n"); 
     getchar(); 
    } 
    } 
    return f; 
} 

/* Multiplies a * b in the form of strings st1 and st2. */ 
/* ************************************************************************ */ 
char *mulstr(char *st1, char *st2, int *s) { 
    char *m1 = st1, *m2 = st2, *p1 = NULL, *p2 = NULL; 
    char **lines = NULL; 
    char *swap = NULL; 
    int i, j, k, l2 = 0, l1 = 0, cr; 
    if(strlen(st1) < strlen(st2)) { 
    m1 = st2; 
    m2 = st1;     /* Pointer to the short string */ 
    } 
    l2 = strlen(m2); 
    l1 = strlen(m1); 
    if((lines = (char**)malloc(sizeof(char*) * l2)) == NULL) { 
    perror("Allocation lines 0"); 
    exit(1); 
    } 
    for(i = 0; i < l2; i++) { 
    if((lines[i] = (char*)malloc(l1 + l2 + 2)) == NULL) { 
     perror("Allocation 1"); 
     exit(1); 
    } 
    } 
    p2 = m2 + l2 - 1; 
    i = 0; 
    cr = 0; 
    while(p2 >= m2) { 
    int n2 = *p2 - 48, n5 = 0; 
    j = 0; 
    p1 = m1 + l1 - 1; 
    cr = 0; 
    while(p1 >= m1) { 
     int n1 = *p1 - 48, n3 = n1 * n2 + cr, n4 = n3/10; 
     n5 = n3 % 10; 
     lines[i][j++] = n5 + 48; 
     cr = n4; 
     p1--; 
    } 
    lines[i][j++] = cr + 48; 
    lines[i][j] = 0; 
    for(k = i; k < l2 - 1; k++) 
     strcat(lines[i], "0"); 
    lines[i] = reverse(lines[i]); 
    for(k = 0; k < i; k++) 
     strcat(lines[i], "0"); 
    i++; 
    p2--; 
    } 
    if(*s < l1 + l2 + 2) { 
    *s = l1 + l2 + 2; 
    if((st1 = (char*)realloc(st1, *s)) == NULL) { 
     perror("Allocation st1 re"); 
     exit(1); 
    } 
    } 
    memset(st1, 48, l1 + l2 + 2); 
    *(st1 + l1 + l2 + 1) = 0; 
    cr = 0; 
    for(k = l1 + l2 - 1; k >= 0; k--) { 
    int dtot = 0, d1, d2; 
    for(i = 0; i < l2; i++) 
     dtot += (lines[i][k] - 48); 
    dtot += cr; 
    d1 = dtot/10; 
    d2 = dtot % 10; 
    cr = d1; 
    st1[k + 1] = d2 + 48; 
    } 
    st1[0] = cr + 48; 
    st1[l1 + l2 + 1] = 0; 
    if((swap = (char*)malloc(*s)) == NULL) { 
    perror("Allocation swap"); 
    exit(1); 
    } 
    strcpy(swap, st1); 
    while(*swap && *swap == '0') 
    memmove(swap, swap + 1, strlen(swap)); 
    strcpy(st1, swap); 
    free(swap); 
    for(i = 0; i < l2; i++) 
    free(lines[i]); 
    free(lines); 
    return st1; 
} 

/* Reverses a string of digits. */ 
/* ************************************************************************ */ 
char *reverse(char *rv) { 
    int ln = strlen(rv); 
    char *p = rv + ln - 1, *tmp = alloca(ln + 1); 
    int j = 0; 
    if(!tmp) { 
    perror("Allocation tmp"); 
    exit(1); 
    } 
    while(p >= rv) { 
    *(tmp + j++) = *p; 
    p--; 
    } 
    *(tmp + j) = 0; 
    strcpy(rv, tmp); 
    return rv; 
} 

/* 'subtracts' 1 from a string of digits. */ 
/* ************************************************************************ */ 
char *subone(char *sb) { 
    char *p = sb + strlen(sb) - 1; 
    char *swap = alloca(strlen(sb) + 1); 
    while(p >= sb) { 
    int dig = *p - 48; 
    if(dig > 0) { 
     *p = dig + 47; 
     break; 
    } 
    else 
     *p = 57; 
    p--; 
    } 
    strcpy(swap, sb); 
    while(*swap && *swap == '0') 
    memmove(swap, swap + 1, strlen(swap)); 
    strcpy(sb, swap); 
    return sb; 
} 

答えて

1

factを呼び出すたびに、返されたポインタを保存します。関数が戻る前に、freeその関数内に格納されているポインタ。基本的には、割り当てたメモリに対して、割り当てられた同じ関数内のメモリを解放するか、呼び出し元にそのメモリへのポインタを返し、呼び出し元が解放前に解放するようにします。

関連する問題