Retorno de referências a variáveis locais

Retornar referências a variáveis locais é um erro comum entre muitos programadores inexperientes quando começam a trabalhar com funções que manipulem vetores, seja qual for o tipo em questão, ou mesmo ponteiros. Motivado por isso e por um festival dessas referências que andei presenciando, resolvi tratar o assunto.

Mas você jovem padawan da computação deve estar se perguntando: “Que raios é isso de referência a uma variável local? E qual o problema em retorná-las?”

O retorno de uma referência local se dá quando retornamos um ponteiro (endereço) de um dado ‘X’, sendo ele escopo local, para a função chamadora. Veja o exemplo a seguir, feito em C++…

#include

using namespace std;

int *baz(void);

int main(int argc, char *argv[]){
int *i;
i = NULL;
cout<<"i antes da chamada a baz(): “<Compilando temos:

$g++ baz.cpp -o baz
baz.cpp: In function ‘int *baz()’:
baz.cpp:5: Warning: address of local variable ‘k’ returned

Sim! Um Warining… nada demais, quem nunca utilizou um código mesmo com warnings? Mas esse warning é um perigo! E vocês já saberão o porque.

Continuando, agora vamos executar:

$./baz
i antes da chamada a baz(): <null>
valor de k: 8
i apos a chamada de baz(): 8

É… deu certo. Melhor tentarmos um exemplo mais elaborado. É praticamente a mesma coisa, exceto que dessa vez iremos encher linguiça PILHA:

#include
#include

using namespace std;

int *baz(void);
void do_nothing(void);

int main(int argc, char *argv[]){
int *i;
i = NULL;
cout<<"i antes da chamada a baz(): “<E o resultado da execução:

$./baz
i antes da chamada a baz(): <null>
valor inicial de k: 8
i apos a chamada de baz(): 8
Eu nao faco nada!!! so encho a PILHA!
i apos chamada de baz(): 134519904 <——AHÁÁÁÁÁÁÁÁ

Aí está! A variável ‘i’ se corrompeu! Não ela não foi pro lado negro da Força, ela possui dados duvidosos e, portanto, inválidos (e põe inválidos nisso).

Mas porque? Tudo estava funcionando tão bem!

A explicação se baseia no conceito de pilha de dados no programa; Essa pilha é onde são empilhadas as variáveis das funções e os endereços de retorno para a função chamadora, seria mais ou menos assim:

Como uma pilha de dados funciona.

No primeiro exemplo o retorno do endereço de k não foi prejudicado pois a área na pilha onde a função, e conseqüentemente os dados, estavam alocados havia sido removida, mas não sobrescrita (nessa tipo de remoção, ao contrário da estrutura de dados pilha, apenas o ponteiro topo “desce” para o elemento abaixo), ou seja, os dados estavam, por pura sorte, preservados; Mas ao chamarmos as funções pow() e do_nothing(), no segundo exemplo, a pilha foi sobrescrita , causando o corrupção natural e correta da informação que residia no endereço onde inicialmente estava k enquanto sua função ainda executava.

Bem, a idéia desse meu primeiro post era essa, trazer a você, iniciante em programação, uma idéia geral de porque não retornar um referência a uma variável local. Afinal de contas esse tipo de retorno não se faz necessário uma vez que poderíamos passar uma variável que recebesse esse endereço como parâmetro da função, ou na pior das hipóteses retornar uma referência a variável local, desde que esta seja declarada como estática (static). Entretanto, apesar de segura essa última abordagem deve ser evitada uma vez que a variável em questão passaria a atuar quase como global, entre a função chamada e a função chamadora, o que não é boa prática de programação.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: