2

I'm using a function which integrates a polynomial which is given to the function as a pointer argument. Inside the function I use a malloc in order to allocate memory for the integrated polynomial which will be returned.

The problem is, I cannot free it before returning it to the main function, cause then I would be returning nothing. But if I free it after returning it then I'm obviously doing nothing because the program will return to the main function before reading the free.

Here's the function.

double * integrar(int n, double *dp, double *mitjana) {

double *p, mitj = 0;
int i;

p = (double *)malloc((n + 2)*sizeof(double));
if(p == NULL) {printf("\nError de memoria.\n"); exit(1);}

p[0] = 1;

for(i = 1; i <= n + 1; i++)
    p[i] = dp[i - 1]/i;

for(i = 0; i <= n + 1; i++)
    mitj += p[i];

mitj = mitj/(n + 2);
*mitjana = mitj;

return p; }

I need to somehow free p. Here's the main function:

int main(void) {

int n, k, i, j;
double mitjmax, mitjaux, **p;
mitjmax = 0;

printf("Dona el grau del polinomi.\n");
scanf("%d", &n);
printf("\nDona el nombre de vegades que el vols integrar.\n");
scanf("%d", &k);

p = (double **)malloc((k + 1)*sizeof(double *));
if(p == NULL) {printf("\nError de memoria.\n"); exit(1);}
for(i = 0; i < k + 1; i++) {
    p[i] = (double *)malloc((n + 1 + i)*sizeof(double));
    if(p[i] == NULL) {printf("\nError de memoria.\n"); exit(1);}
}

printf("\nDona el polinomi.\n");
for(i = 0; i <= n; i++)
    scanf("%le", &p[0][i]);

for(i = 0; i <= n; i++)
    mitjmax += p[0][i];
mitjmax = mitjmax/(n + 1);

for(i = 1; i <= k; i++) {
    p[i] = integrar(n + i - 1, p[i - 1], &mitjaux);
    if(mitjaux > mitjmax)
        mitjmax = mitjaux;
}

for(i = 0; i <= k; i++) {
    printf("grau %d:", i + n);
    for(j = 0; j <= n + i; j++)
        printf("%11.4le ", p[i][j]);
    printf("\n");
}
printf("El maxim de les mitjanes dels coeficients: %le\n", mitjmax);

for(i = 0; i <= k; i++)
    free(p[i]);
free(p);

return 0;
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Lextrick
  • 21
  • 2
  • 4
    As far as memory management is concerned your code looks OK to. I'm not sure what the problem is. – Jabberwocky Mar 17 '20 at 10:29
  • 1
    You're returning a pointer, so, if you use it after the function, then you must not free it. I don't see an issue with that – samthegolden Mar 17 '20 at 10:30
  • 3
    How do you conclude there's a memory leak? – samthegolden Mar 17 '20 at 10:31
  • Especially the sentence: _" But if I free it after returning it then I'm obviously doing nothing because the program will return to the main function before reading the free."_ doesn't really make sense to me. – Jabberwocky Mar 17 '20 at 10:31
  • 1
    most likely you have a leek in `main`. You have 2 loops and do mallocs in the first one, then you replace the malloced value with the return from the function. `free` only frees the last one, but you loose the first. – Serge Mar 17 '20 at 10:32
  • Well, when executing it with these data: n = 2 (polynomial degree), k = 4 (times to be integrated), and the coeficients of the polynomial being: -3 2 -1 valgrind says that there are 176 which are definitely lost in 4 blocks, I don't see any problem too but that is what valgrind says so I don't really know what to do. – Lextrick Mar 17 '20 at 10:34
  • Jabberwocky, I mean, I'm using a malloc inside function integrar, I don't really know if I then have to free it. If not then okey, but if I do then how do I free it? I mean free(p) before return p; makes no sense, but neither does return p; and then free(p);. Anyways, as other have pointed out it seems that it is not necessary. Let me know what you thing please. – Lextrick Mar 17 '20 at 10:38
  • @Lextrick Don't free p inside `integrar`, that would be pointless. But the answer below is what you're looking for. The `integrar` function itself is fine. – Jabberwocky Mar 17 '20 at 10:40
  • Serge, I'll don't really understand that, could you please explain more elaborately. Anyways I'll have a look atit, thank you. – Lextrick Mar 17 '20 at 10:41
  • 2
    @Lextrick I'm not 100% sure ( I didn't look deep into your code), but I think the first `for(i = 0; i < k + 1; i++)` loop should be removed, you don't need to allocate memory here, the memory allocation is done in `integrar`. – Jabberwocky Mar 17 '20 at 10:42
  • As a side note, array indexing starts at 0. All attempts to subvert this and make it start at 1 instead **WILL** bite you later. – n. m. could be an AI May 21 '22 at 08:39
  • (1) `malloc` returns a pointer to allocated data to the caller. The caller must `free` it somewhere. (2) Your function returns a pointer to allocated data to the caller. The caller must `free` it somewhere. Do you see anything dangerous in the second case which is not present in the first case? – n. m. could be an AI May 21 '22 at 08:41
  • "I don't really know if I then have to free" You do know. You have to free. There are no ifs or buts. The question is where. You are returning a block of data to the caller so that the caller can use it. You `free` a block of data after you use it. So the caller must `free`. So when documenting `integrar` you should write down "the function returns a block of `malloc`'d data to the caller, the caller should `free` it". – n. m. could be an AI May 21 '22 at 08:46

1 Answers1

2

As long as you document it properly, there is nothing wrong with not freeing malloc()ed memory which is then returned to the caller.

Especially in libraries, the caller must be aware that it is their possibility to free the memory and it must as well be obvious how to do so.

But in the shoes of the caller, you must be aware what happens to your pointers and how to use it. You can see the call to integrar() as an (indirect) call to malloc(), so the real problem is your assignment p[i] = (double *)malloc((n + 1 + i)*sizeof(double)); followed by p[i] = integrar(n + i - 1, p[i - 1], &mitjaux); without intermediate free(p[i]), because then the first malloc()ed memory is essentially lost.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • Hey, thank you. I've changed that part for p[0] = (double *)malloc((n + 1)*sizeof(double)); and now valgrind says there are no memory leaks! – Lextrick Mar 17 '20 at 11:08
  • @Lextrick Yes, for only `p[0]`, that should be fine (although you [shouldn't cast the return value of `malloc()`](https://stackoverflow.com/q/605845/296974)) – glglgl Mar 17 '20 at 14:00