é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

1. é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 20/06/2017 - 23:41h


static char *buf;

if (!(buf = realloc(buf, SIZE)))
exit(1);

sprintf(buf, "%s/%s", str01, str02);

return buf;

veja o código acima, obviamente é um exemplo, realmente é necessario liberar a ram alocada aquele pointeiro?
pergunto isso pois o valgrind aponta como "still reachable", que pelo que sei não representa perigo, e também
uma função do openbsd(/bin/cp/util.c) faz o mesmo (acredito eu, não cheguei a ler todo o codigo)


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 21/06/2017 - 08:29h

O fato de o ponteiro que aponta para a área ser estático não faz com que a área apontada se comporte como memória estática.

Veja este exemplo, ligeiramente diferente do seu.

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

void f(void){
static char *buf;
buf=calloc(4096, 4096); // Aloca 16MiB
printf("%p\n", buf);
}

int main(void){
for(int i=0; i<10; ++i){
printf("%d: ", i);
f();
}
}


Dá para ver que há vazamento de memória, pois o ponteiro vai apontando cada vez para posições diferentes.

No seu caso, porém, você realoca a mesma região de memória, e interrompe o programa se a realocação falhar. Esse fato de matar o programa em caso de falha na realocação é crucial para não haver vazamento. O seu ponteiro, a qualquer momento da execução do programa, vai ser ou nulo ou vai apontar para uma região bem definida, alocada ou realocada sucessivas vezes, sem provocar vazamentos.

Contudo, o valgrind não faz uma análise semântica do seu programa, mas, grosso modo, se limita a ver se aquilo que foi alocado durante a vida do programa é efetivamente desalocado antes de o programa terminar.

Se você quiser calar o valgrind (e, no fundo, se desfazer da engenhosidade do seu esquema), poderia transformar seu ponteiro em global (ou com escopo de arquivo), e criar uma função de desalocação, que você poderia registrar com atexit(). Contudo, para que essa estratégia de calar funcionasse mesmo, você teria de mudar um pouco o modo de chamar realloc(), deixando-o mais canônico, a fim de evitar a perda de referência à região alocada caso a realocação falhasse (caso em que realloc() devolveria o valor NULL).

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

static char *buf; // buf com escopo de arquivo (não visível por outros módulos).

void cleanbuf(void){
free(buf);
}

void f(void){
static size_t size=1048576;
void *ptr_aux;
ptr_aux=realloc(buf, size*=2);
if(!ptr_aux)
exit(1);
buf=ptr_aux;
printf("%p\n", buf);
}

int main(void){
atexit(cleanbuf);
for(int i=0; i<10; ++i){
printf("%d: ", i);
f();
}
}


3. Re: é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 21/06/2017 - 21:25h

@paulo1205: no caso de chamar (m, c)alloc ao invés de realloc você perde as referencias anteriores, então o vazamento é inevitável. Mas eu me refiro a este caso em especifico sem perder a referencia, é realmente necessário liberar este ponteiro? (alias me referi a ponteiros estáticos pq no caso eu faria referência sempre ao mesmo ponteiro)




4. Re: é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 21/06/2017 - 21:52h

Como eu disse, não é necessário liberar a memória, já que o fim do programa implica necessariamente que ela será liberada. Só que o valgrind não faz análise semântica, logo não tem como saber que o programa intencionalmente deixou de fazer a liberação, em vez de isso ter acontecido por causa de esquecimento, perda de referência ou outros bugs.

Note que eu reconheci que a construção é engenhosa, mas não é compatível com valgrind em modo default. Não conheço o valgrind a ponto de poder dizer se ele tem opções de execução ou de embutir no código, para que uma alocação em especial seja ignorada pelo rastreamento de alocações.

Fora isso, só se você ignorar a saída, ao menos sobre esse bloco, o que seria quase a mesma coisa que simplesmente não rodar o valgrind.


5. Re: é necessario liberar memoria alocada em ponteiro estatico?

Perfil removido
removido

(usa Nenhuma)

Enviado em 21/06/2017 - 21:59h

paulo1205 escreveu:
Como eu disse, não é necessário liberar a memória, já que o fim do programa implica necessariamente que ela será liberada.

Mas o trabalho de ser liberado dependera do kernel para isso? por exemplo um kernel que não tente retomar a memória teria problemas? (me lembro de ter lido sobre um kernel que caso a memória seja vazada ele não tentava retomar a memória)

paulo1205 escreveu:
Só que o valgrind não faz análise semântica, logo não tem como saber que o programa intencionalmente deixou de fazer a liberação, em vez de isso ter acontecido por causa de esquecimento, perda de referência ou outros bugs.

Note que eu reconheci que a construção é engenhosa, mas não é compatível com valgrind em modo default. Não conheço o valgrind a ponto de poder dizer se ele tem opções de execução ou de embutir no código, para que uma alocação em especial seja ignorada pelo rastreamento de alocações.

Fora isso, só se você ignorar a saída, ao menos sobre esse bloco, o que seria quase a mesma coisa que simplesmente não rodar o valgrind.

O problema ser ignorado pelo valgrind é o de menos, tendo certeza que algum problema citado pelo mesmo é um falso positivo não há motivos para se preocupar com a saída




6. Re: é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/06/2017 - 00:22h

katsuke00 escreveu:

Mas o trabalho de ser liberado dependera do kernel para isso? por exemplo um kernel que não tente retomar a memória teria problemas? (me lembro de ter lido sobre um kernel que caso a memória seja vazada ele não tentava retomar a memória)


No mundo UNIX, a memória destinada a um processo específico é totalmente liberada quando tal processo termina. Até existem mecanismos pelos quais um processo pode ter dados numa região de memória compartilhada ou compartilhável com outros processos, mas a obtenção desses recursos se dá por outros mecanismos, diferentes dos meios normais de alocação de memória.

Outros sistemas que eu conheço normalmente têm regras parecidas, com o meio principal de alocação de memória entregando um recurso que é automaticamente devolvido ao SO ao final do processo, e outros mecanismos, de uso mais especializado, para o caso de alocações que tenham de sobreviver além da execução do programa.

O problema ser ignorado pelo valgrind é o de menos, tendo certeza que algum problema citado pelo mesmo é um falso positivo não há motivos para se preocupar com a saída.


Sendo assim, não há com o que se preocupar. Sua construção é segura pois qualquer realocação bem sucedida vai ou reaproveitar a área previamente alocada (estendendo ou reduzindo o tamanho do bloco que a contém) ou vai alocar uma área nova e automaticamente liberar a anterior. Já se a alocação falhar, o encerramento obrigatório do processo, que você acertadamente empregou, vai devolver toda a memória que o processo tenha usado.


7. Re: é necessario liberar memoria alocada em ponteiro estatico? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 22/06/2017 - 02:04h

@paulo1205: obrigado então por esclarecer essa duvida








Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts