Retornando um ponteiro para uma variável automática

Digamos que você tenha a seguinte function:

char *getp() { char s[] = "hello"; return s; } 

Como a function está retornando um ponteiro para uma variável local na function a ser usada fora, isso causará um memory leaks?

PS Eu ainda estou aprendendo C então minha pergunta pode ser um pouco ingênua …

[Atualizar]
Então, se você quiser retornar um novo array char[] (isto é, talvez para uma function substring), o que você retorna exatamente? Deve ser ponteiro para uma variável externa? ou seja, um char[] que não é local para a function?

Não causará memory leaks. Isso causará uma referência pendente. A variável local é alocada na pilha e será liberada assim que sair do escopo. Como resultado, quando a function termina, o ponteiro que você está retornando não aponta mais para uma memory que você possui. Isso não é um memory leaks (memory leaks é quando você aloca memory e não a libera).

[Update] : Para poder retornar uma matriz alocada em uma function, você deve alocar a pilha externa (por exemplo, na pilha) como:

 char *test() { char* arr = malloc(100); arr[0] = 'M'; return arr; } 

Agora, se você não free a memory na function de chamada depois de usá-la, você terá um memory leaks.

Não, não vai vazar, pois é destruído depois que getp () termina;

Isso resultará em um comportamento indefinido, porque agora você tem um ponteiro para uma área de memory que não possui mais o que você acha que faz, e que pode ser reutilizada por qualquer pessoa.

Um memory leaks aconteceria se você armazenasse essa matriz na pilha, sem executar uma chamada para free ().

 char* getp(){ char* p = malloc(N); //do stuff to p return p; } int main(){ char* p = getp(); //free(p) No leak if this line is uncommented return 0; } 

Aqui, p não é destruído porque não está na pilha, mas na pilha. No entanto, uma vez que o programa termina, a memory alocada não foi liberada, causando um memory leaks (mesmo que seja feito uma vez que o processo morre).

[ATUALIZAR]

Se você quiser retornar uma nova string C de uma function, você tem duas opções.

  • Armazene-o no heap (como no exemplo acima ou como este exemplo real que retorna uma string duplicada);
  • Passar um parâmetro de buffer

por exemplo:

  //doesnt exactly answer your update question, but probably a better idea. size_t foo (const char* str, size_t strleng, char* newstr); 

Aqui, você teria que alocar memory em algum lugar para newstr (poderia ser stack OU heap) antes de chamar a function foo. Neste caso particular, retornaria a quantidade de caracteres no newstr.

Não é um memory leaks porque a memory está sendo liberada corretamente.

Mas isso é um erro. Você tem um ponteiro para a memory não alocada . É chamado de referência pendente e é uma fonte comum de erros em C. Os resultados são indefinidos. Você não verá problemas até o tempo de execução quando tentar usar esse ponteiro.

As variables ​​automáticas são destruídas no final da chamada de function; você não pode retornar um ponteiro para eles. O que você está fazendo poderia ser descrito como “retornar um ponteiro para o bloco de memory que costumava conter s, mas agora não é usado (mas ainda pode ter algo nele, pelo menos por enquanto) e que será rapidamente preenchido com algo mais completamente. ”

Isso não causará memory leaks, mas causará um comportamento indefinido. Este caso é particularmente perigoso porque o ponteiro apontará para algum lugar na pilha do programa e, se você usá-lo, estará acessando dados randoms. Esse ponteiro, quando escrito, também pode ser usado para comprometer a segurança do programa e fazê-lo executar código arbitrário.

Ninguém mais mencionou outra maneira que você possa tornar esta construção válida: diga ao compilador que você quer que a matriz “s” tenha “duração de armazenamento estático” (isto significa que ela vive pela vida do programa, como uma variável). Você faz isso com a palavra-chave “static”:

 char *getp() { static char s[] = "hello"; return s; } 

Agora, a desvantagem disso é que agora há apenas uma instância de s, compartilhada entre todas as invocações da function getp (). Com a function que você escreveu, isso não importará. Em casos mais complicados, pode não fazer o que você quer.

PS: O tipo usual de variables ​​locais tem o que é chamado de “duração do armazenamento automático”, o que significa que uma nova instância da variável é trazida à existência quando a function é chamada e desaparece quando a function retorna. Há uma palavra-chave correspondente “auto”, mas é implícita de qualquer maneira se você não usa “estática”, então você quase nunca a vê no código do mundo real.

Eu deletei minha resposta anterior depois de colocar o código em um depurador e assistir a desassembly e a janela de memory.

O código na pergunta é inválido e retorna uma referência para empilhar a memory, que será sobrescrita.

Essa versão ligeiramente diferente, no entanto, retorna uma referência à memory fixa e funciona bem:

 char *getp() { char* s = "hello"; return s; } 

s é uma variável de pilha – é automaticamente desprezada no final da function. No entanto, seu ponteiro não será válido e se referirá a uma área de memory que pode ser sobrescrita a qualquer momento.