Retorno de ponteiro [RESOLVIDO]

1. Retorno de ponteiro [RESOLVIDO]

Ednux
ednux

(usa Arch Linux)

Enviado em 22/10/2015 - 12:42h

Estou com dúvidas na seguinte questão.

Considerando que parâmetros e variáveis locais de função e procedimento são desalocados da memória após sua execução, observe a seguinte função implementada na linguagem C:

int *fazAlgo() {
int val = 23, *pt;
pt = &val;
return pt;
}


De acordo com o programa dado, analise as seguintes asserções.

A função fazAlgo está logicamente correta na devolução do endereço armazenado em pt.

PORQUE

Ao término da função fazAlgo, a variável val é desalocada, mas será devolvido o endereço de memória reservado para a variável val, sem problemas de execução.

Sobre as asserções a respeito da função em C dada, marque a alternativa correta.

a) As duas são proposições verdadeiras, e a segunda é uma justificativa correta da primeira.

b) Tanto a primeira quanto a segunda são asserções falsas.

c) A primeira é uma proposição falsa, e a segunda verdadeira.

d) As duas são proposições verdadeiras, e a segunda não é uma justificativa correta da primeira.

e) A primeira é uma proposição verdadeira, e a segunda falsa.



Eu fiz esse código para teste:
#include <stdio.h>

int *fazAlgo(void);

int main(void) {
int *x;

x = fazAlgo();
printf("X = %d\n", *x);

*x = 10;
printf("X = %d\n", *x);

return 0;
}

int *fazAlgo(void)
{
int val = 23, *pt;
pt = &val;
return pt;
}


Funciona sem qualquer erro ou aviso.
A resposta dessa questão de acordo com o gabarito é letra b, mas por quê ?
Eu acho que alocando dessa forma e retornando o endereço pode ocorrer do sistema operacional liberar esse endereço para outro programa ou variável, visto que ele "pensa" que o endereço está vago, é isso ?


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/10/2015 - 13:37h

As duas são falsas.

var é uma variável com alocação automática (i.e. o compilador emite código no ponto em que a variável é declarada para que espaço seja reservado para ela somente na hora da execução, e também o código correspondente de liberação de espaço ao final do bloco em que a declaração reside).

Quando a função fazAlgo() começa a executar, reserva-se espaço para ela e coloca-se lá um valor. Quando a função termina, o valor que havia sido armazenado não é alterado, mas a posição de memória que havia sido usada para armazená-lo é devolvida ao ambiente de execução, para que ele possa reaproveitar como quiser.

No seu programa, você deu o azar de pegar o valor preservado que havia sido atribuído dentro de fazAlgo(), mas apenas porque nenhuma outra parte do programa solicitou alocação automática e reaproveitou aquele espaço com outra finalidade.

Tente este programa aqui (que eu não garanto que vá funcionar). Possivelmente ele vai imprimir 5, em vez de 0, porque a segunda função pode aproveitar o mesmo espaço usado pela variável local da primeira para sua própria variável local.

#include <stdio.h>

int *p_zero(void){
int a=0;
return &a;
}

void five(void){
int b=0;
b+=5;
}

int main(void){
int *p_i;
p_i=p_zero();
five();
printf("%d\n", *p_i);
return 0;
}


Note, porém, que o compilador possivelmente não deixa código assim passar batido. Aqui, ao compilar o programa, eu recebi a seguinte mensagem de aviso (mesmo sem solicitar aviso algum).

$ gcc x.c -o x
x.c: In function ‘p_zero’:
x.c:5:3: warning: function returns address of local variable [-Wreturn-local-addr]
return &a;
^


3. Re: Retorno de ponteiro [RESOLVIDO]

Ednux
ednux

(usa Arch Linux)

Enviado em 22/10/2015 - 14:02h

Obrigado Paulo,

Eu recebi o mesmo aviso, porém o código dá Segmentation fault na hora de executar.
Alterando a função para:
int *p_zero(void){
int a=0, *pt;
pt = &a;
return pt;
}

Ele executa e imprime zero.
Bom, então é isso mesmo... Pode acontecer de ele usar o mesmo endereço ou não.
Só consigo fazer ele imprimir 5, caso eu mude dentro da main, tipo isso:
*p_i = 5; 




4. Re: Retorno de ponteiro [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/10/2015 - 16:53h

ednux escreveu:

Obrigado Paulo,

Eu recebi o mesmo aviso, porém o código dá Segmentation fault na hora de executar.


Pois é. Na minha máquina imprimiu cinco. Mas é o tipo de resultado que eu chamo mesmo de “por azar”, porque é imprevisível o que pode acontecer quando você usa essa memória inválida.

Que mal lhe pergunte, qual sua arquitetura e versão do SO e do compilador? No meu caso, estou com Ubuntu 14.01 64 bits, e GCC 4.8.2.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts