C утечка памяти с двойными указателями - PullRequest
0 голосов
/ 08 мая 2018

Почему это не работает? У меня утечка памяти, но я не знаю где. Программа вылетает и печатает случайные символы.

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

char** createPyramid(int depth);

int main(int argc, char** argv) {
    printf("\n createPyramid \n");
    int depth = 9;
    char** w = createPyramid(depth);
    for (int i=0;i<depth;i++){
        printf("%s \n",w[i]);
    }
    for (int i = 0;i<depth;i++){
        free(w[i]);
    }
    free(w);
    return 0;
}

char** createPyramid(int depth){
    char** w;
    w = (char**) calloc(depth,sizeof(char));
    for (int i=0;i<depth;i++){
        *(w+i)=(char*) calloc(i+2,sizeof(char));
        for (int j=0;j<i+1;j++){
            (*((*(w+i))+j))='*';
        }
        *((*(w+i))+i+1)='\0';
    }
    return w;
}

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Поскольку мы можем вычислить, сколько пространства займет вся глубина пирамиды, прежде чем строить ее, мы можем упростить код, выделив один буфер.

Первый слой занимает 2 char с (один для *, один для \n). Затем следующий слой занимает столько же, сколько и предыдущий, плюс n экземпляров * и окончательный \n. Таким образом, общий размер:

f(n) = f(n-1) + n + 1
f(1) = 2

Решение этого рекуррентного уравнения дает нам:

f(n) = n * (n+3) / 2

Теперь мы можем легко написать всю пирамиду:

char * createPyramid(int depth)
{
    int i, j;
    int size = depth * (depth + 3) / 2;
    char * buffer = malloc(size + 1);
    char * p = buffer;

    for (i = 0; i < depth; ++i) {
        for (j = 0; j < i + 1; ++j)
            *p++ = '*';
        *p++ = '\n';
    }
    *p = 0;

    return buffer;
}

И распечатать за один раз:

int main()
{
    int depth = 9;
    char * buffer = createPyramid(depth);
    puts(buffer);
    free(buffer);
    return 0;
}

Конечно, обратите внимание, что если вам нужна программа, которая просто печатает пирамиду, вам даже не нужна динамическая память.

0 голосов
/ 08 мая 2018

Как указано в комментариях, проблема заключается в выделении места для символа **. Кроме того, использование индексации вместо арифметики указателей более понятно. Это работает:

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


char** createPyramid(int depth);                                                                

int main(int argc, char** argv) {                                                               
    printf("\n createPyramid \n");                                                              
    int depth = 9;                                                                              
    char** w = createPyramid(depth);                                                            
    for (int i=0;i<depth;i++){                                                                  
        printf("%s \n",w[i]);                                                                   
    }                                                                                           
    for (int i = 0;i<depth;i++){                                                                
        free(w[i]);                                                                             
    }                                                                                           
    free(w);                                                                                    
    return 0;                                                                                   
}                                                                                               

char** createPyramid(int depth){                                                                
    char** w;                                                                                   
    w = (char**) calloc(depth,sizeof(char*));                                                   
    for (int i=0;i<depth;i++){                                                                  
        w[i] =(char*) calloc(i+2,sizeof(char));                                                 
        for (int j=0;j<i+1;j++){                                                                
            w[i][j] = '*';                                                                      
        }                                                                                       
        w[i][i+1] = '\0';                                                                       
    }                                                                                           
    return w;                                                                                   
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...