2009-08-03 22 views
9

Digamos que tiene la siguiente función:Devolver un puntero a una variable automática

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

Dado que la función devuelve un puntero a una variable local en la función que se utiliza fuera, va a provocar una pérdida de memoria?

P.S. Todavía estoy aprendiendo C por lo que mi pregunta puede ser un poco ingenuo ...

[Actualización]
lo tanto, si dice que desea devolver un nuevo char[] array (es decir, tal vez por una función de subcadena), lo ¿regresas exactamente? ¿Debería ser un puntero a una variable externa? es decir, un char[] que no es local para la función?

Respuesta

24

No causará una pérdida de memoria. Causará una referencia colgante. La variable local se asigna en la pila y se liberará tan pronto como salga del alcance. Como resultado, cuando la función finaliza, el puntero al que regresa ya no apunta a la memoria que posee. Esto no es una pérdida de memoria (la pérdida de memoria se produce cuando asigna parte de la memoria y no la libera).

[Actualización]: Para poder devolver una matriz asignada en una función, debe asignarlo pila exterior (por ejemplo, en el montón) como:

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

Ahora, si no' t free la memoria en la función de llamada después de que termine de usarlo, tendrá una pérdida de memoria.

+0

¿Es necesario asignar 'arr [0] = 'M';' o fue solo para demostrar una operación no trivial en 'arr'? – user1717828

+0

@ user1717828 este último. –

13

No, no tendrá fugas, ya que se destruye después de que termina getp();

Esto dará como resultado un comportamiento indefinido, porque ahora tiene un puntero a un área de memoria que ya no contiene lo que cree que lo hace, y que puede ser reutilizado por cualquier persona.

Se produciría una pérdida de memoria si almacenó esa matriz en el montón, sin ejecutar una llamada a 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; 
} 

Aquí, p no se destruye porque no está en la pila, sino en el montón. Sin embargo, una vez que finaliza el programa, la memoria asignada no se ha liberado, lo que provoca una pérdida de memoria (aunque se realice una vez que el proceso se agota).

[ACTUALIZACIÓN]

Si desea devolver un nuevo C-secuencia de una función, tiene dos opciones.

  • tienda que en el montón (como el ejemplo encima o como this real example que devuelve una cadena duplicada);
  • pasar un parámetro memoria intermedia

por ejemplo:

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

Aquí, tendríamos que asignar memoria en algún lugar de newstr (podría ser la pila o montón) antes de llamar a la función foo. En este caso particular, devolvería la cantidad de caracteres en newstr.

8

No se trata de una pérdida de memoria porque la memoria se está liberando correctamente.

Pero es un error. Tiene un puntero a sin asignar memoria. Se llama dangling reference y es una fuente común de errores en C. Los resultados no están definidos. No verá ningún problema hasta el tiempo de ejecución cuando intente usar ese puntero.

0

s es una variable de pila: se elimina automáticamente la referencia al final de la función. Sin embargo, su puntero no será válido y se referirá a un área de memoria que podría sobrescribirse en cualquier punto.

+0

No está desreferenciado, pero ya no se asigna en la pila. –

2

No causará pérdida de memoria, pero causará un comportamiento indefinido. Este caso es particularmente peligroso porque el puntero apunta a algún lugar en la pila del programa, y ​​si lo usa, accederá a datos aleatorios. Dicho puntero, cuando se escribe, también se puede usar para comprometer la seguridad del programa y hacer que ejecute código arbitrario.

3

Las variables automáticas se destruyen al final de la llamada a la función; no puedes devolverles un puntero. Lo que estás haciendo se podría describir como "devolver un puntero al bloque de memoria que solía contener s, pero ahora no se usa (pero podría tener algo en él, al menos por ahora) y eso se llenará rápidamente con algo si no del todo ".

+0

+1 por no usar la palabra "pila". – sigjuice

1

He eliminado mi respuesta anterior después de poner el código en un depurador y ver el desmontaje y la ventana de memoria.

El código de la pregunta no es válido y devuelve una referencia a la memoria de la pila, que se sobrescribirá.

Esta versión ligeramente diferente, sin embargo, devuelve una referencia a la memoria fija, y funciona bien:

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

char s * ??? ¿Esto está permitido en C? – Alphaneo

+1

error tipográfico ... ya sabes que quería decir char * s – abelenky

2

Nadie más aún ha mencionado otra manera que usted puede hacer este constructo válido: decirle al compilador que usted quiere que la matriz "s" tenga "duración de almacenamiento estática" (esto significa que vive durante la vida del programa, como una variable global). Esto se hace con la palabra clave "estática":

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

Ahora, la desventaja de esto es que ahora sólo hay uno instancia de s, compartida entre cada invocación de la función GETP(). Con la función tal como la has escrito, eso no importará. En casos más complicados, es posible que no haga lo que desea.

PD: El tipo habitual de variables locales tiene lo que se denomina "duración de almacenamiento automático", lo que significa que una nueva instancia de la variable aparece cuando se llama a la función y desaparece cuando la función vuelve. Hay una palabra clave correspondiente "auto", pero está implícita de todos modos si no usas "estática", por lo que casi nunca la ves en el código del mundo real.

+0

¿Las referencias 'estáticas' están almacenadas en el Heap? –

+1

No, se cargan/crean al iniciar el programa, por lo que la memoria para ellos generalmente se asigna de forma similar a la memoria que contiene el texto del programa. – caf

Cuestiones relacionadas