Dúvida sobre ponteiros! [RESOLVIDO]

1. Dúvida sobre ponteiros! [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 06/01/2023 - 05:47h

Bom dia a todos. Minha dúvida tem relação a um outro tópico AULA explicado pelo Paulo: https://www.vivaolinux.com.br/topico/C-C++/Duvida-Basica-sobre-ponteiro/
Eu ainda estou estudando o tópico, por ter bastante coisa ainda pra entender! Mais uma vez agradeçendo ao Paulo pelas enormes aulas, uma hora vou entender sobre ponteiros!
As perguntas abaixo são apenas pra ter certeza se entendi o tópico acima corretamente!

Questão 1:
1) Comando free em ponteiros. Entendi que na declaração abaixo, eu não tenho que usar o free! Correto?
2) Entendi que free somente se usa com malloc e etc... certo?
char *Texto;
scanf("%m[\10-\377]", &Texto); // Uso o ponteiro aqui
// free(Texto); // Não é pra ser usado aqui certo?
Fim do programa

Questão 2:
1) Entendi que posso fazer da forma que informo abaixo sem dar bugs no meu programa
2) Entendi que posso sempre mudar o valor do ponteiro, o que ocorre é que ele vai alocar isso em outro lugar novo na memória, deixando como lixo os antigos valores na memória até que o programa seja encerrado.
3) Entendi que bagunçei minha memória, pq perco o controle do que foi alocado anteriormente.
4) Se tenho um ponteiro dentro de uma função, a memória que ele usou é liberada qdo sai da função? Ou também segue a regra de liberar somente qdo o programa encerra?
5) Mas toda a memória é liberada qdo o programa for finalizado Correto?
const char *Ptr = "Mini Text";
Ptr = "Texto muito Maior que o Mini Text";
Ptr = "Imagine aqui um Texto com 100.000 Caracteres";
Ptr = "Imagine aqui um Texto com 500.000 Caracteres";
Fim do programa, a memória que os ponteiros usaram, está liberada no meu S.O sem problemas certo?



  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 12/01/2023 - 05:54h

ApprenticeX escreveu:

Questão 1:
1) Comando free em ponteiros. Entendi que na declaração abaixo, eu não tenho que usar o free! Correto?
2) Entendi que free somente se usa com malloc e etc... certo?
char *Texto;
scanf("%m[\10-\377]", &Texto); // Uso o ponteiro aqui
// free(Texto); // Não é pra ser usado aqui certo?
Fim do programa


Você não precisa usar se for sair do programa imediatamente depois, mas é geralmente considerado uma prática boa você liberar o que alocou, e só contar com a limpeza automática do SO quando você tiver de sair do programa por causa de alguma situação crítica, que o programa não tem como tratar. Uma ferramenta como o Valgrind possivelmente vai reclamar se o programa sair por vias normais sem desalocar o que alocou.

Eu não sei se, nesse caso especificamente, você achou que não deveria chamar free() porque a alocação não foi explicitamente feita por uma função da família de malloc()/calloc()/realloc(). No entanto, como eu cheguei a mencionar ao longo do tópico antigo que você mencionou, é possível que outras funções da biblioteca façam alocações de dados usando internamente malloc() e companhia. É o caso da alocação dinâmica feita por scanf(), de modo que é seguro você desalocar com free() algo que tenha sido alocado por essa função (leia a man page de scanf()).

Questão 2:
1) Entendi que posso fazer da forma que informo abaixo sem dar bugs no meu programa
2) Entendi que posso sempre mudar o valor do ponteiro, o que ocorre é que ele vai alocar isso em outro lugar novo na memória, deixando como lixo os antigos valores na memória até que o programa seja encerrado.
3) Entendi que bagunçei minha memória, pq perco o controle do que foi alocado anteriormente.
4) Se tenho um ponteiro dentro de uma função, a memória que ele usou é liberada qdo sai da função? Ou também segue a regra de liberar somente qdo o programa encerra?
5) Mas toda a memória é liberada qdo o programa for finalizado Correto?
const char *Ptr = "Mini Text";
Ptr = "Texto muito Maior que o Mini Text";
Ptr = "Imagine aqui um Texto com 100.000 Caracteres";
Ptr = "Imagine aqui um Texto com 500.000 Caracteres";
Fim do programa, a memória que os ponteiros usaram, está liberada no meu S.O sem problemas certo?


Nesse caso, você tema mesma variável de tipo ponteiro que, ao longo do tempo, é usada para apontar para quatro constantes literais de strings diferentes. Essas constantes literais residem em posições fixas do programa — fixadas pelo compilador e linker durante a compilação e geração do executável. O ponteiro Ptr é uma variável que guarda apenas um endereço, e, nas quatro linhas acima, tem esse valor de endereço alterado quatro vezes (uma na inicialização e em cada uma das três atribuições posteriores): no primeiro momento, o endereço armazenado corresponde à posição de memória do primeiro caráter da primeira constante literal de string, depois o endereço do primeiro caráter da segunda constante literal de string, depois o endereço do primeiro caráter da terceira string, e, por fim, o endereço do primeiro caráter da quarta string.

Não existe alocação ou realocação cada vez que você muda o endereço contido na variável. As constantes literais de string, como dito acima, são fixas. O seu ponteiro simplesmente aponta para (o primeiro caráter de) cada uma delas em diferentes momentos ao longo da vida do programa.

Ponteiro e alocação não são coisas necessariamente relacionadas. Constantes literais, por exemplo, são alocadas de uma vez por todas durante a compilação/geração do executável, e é possível que vários ponteiros apontem para a mesma constante literal ao longo da vida do programa, ou mesmo que nenhum ponteiro o faça, se tal necessidade não surgir em momento nenhum da execução.

Quando você tem uma função como a seguinte,
void f(void){
const char *ptr="Que lindo dia!";
puts(ptr);
}

não existe alocação nenhuma durante a execução. A string é uma constante literal que faz parte do programa executável e é carregada junto com ele para a memória. Quando a função f() é invocada, a variável ptr dentro dela só copia o endereço do primeiro caráter da constante. e depois é usada para copiar esse mesmo valor de endereço para o argumento de puts(). Por ser uma variável local automática (i.e. não é estática), realmente ptr só existe durante o tempo de execução da função, mas a função só tem de alocar espaço para a a variável ponteiro, que armazena apenas um endereço, não uma cópia do texto.

Isso é diferente das seguintes outras duas funções.
void g(void){
static const char array[]="Que lindo dia!";
puts(ptr);
}
void h(void){
const char array[]="Que lindo dia!";
puts(ptr);
}


Em g(), a variável local array é estática, e está sendo diretamente associada ao valor da constante literal de string. Durante a compilação, o compilador aloca espaço para essa constante literal juntamente com todas as outras constantes do programa. Na invocação de puts(), o compilador substitui diretamente o valor do endereço dessa região alocada para a constante literal de string, sem nenhuma operação intermediária.

Em h(), a variável local array é automática, o que significa que o compilador terá de alocar espaço para o array (quinze bytes: se eu não tiver contado errado, sendo quatorze para o texto e mais um para o byte nulo) cada vez que a função for invocada, e copiar para essa região de memória automática os caracteres da constante literal de string que reside em algum lugar do bloco de memória reservado para as constantes do programa. Na invocação de puts(), o endereço usado será o endereço do array local, que recebeu uma cópia do conteúdo da constante literal, não será o endereço da constante original. Finalmente, quando a função terminar, esses quinze bytes locais serão descartados.


Quando o programa termina, todos os recursos que haviam sido entregues a ele, quer no momento em que o programa em si foi carregado para a memória, quer recursos que ele tenha obtido durante a execução, são liberados.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)

3. Re: Dúvida sobre ponteiros! [RESOLVIDO]

Alexa Bolada
alexabolada

(usa Debian)

Enviado em 06/01/2023 - 05:48h

R: Sim, a memória usada pelo ponteiro é liberada quando o programa é finalizado sem problemas. Uma vez declarado, um ponteiro pode ser usado para mudar o endereço de memória no qual ele aponta, fazendo com que o valor armazenado nele mude. No entanto, isso não significa um novo alocação e sim uma sobreposição na memória. Assim, se os valores atribuídos ao ponteiro foram alocados com malloc, é necessário usar free para limpar a memória usada pelo ponteiro ao sair da função. Lembre-se também de que, ao sair de uma função, a memória alocada pela função é liberada automaticamente.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts