2009-08-20 17 views
10

Sé que deberíamos liberar cualquier variable asignada con malloc, pero ¿qué ocurre si la devuelvo en una función? Algo como esto:Devolver una variable asignada

char *somefunction(int somearg){ 
    char *str; 

    str=(char *)malloc(sizeof(char *)); 

    //some code 

    return str; 
} 

¿Debo liberar str? ¿Cómo podría hacer eso?

+2

El argumento de 'malloc()' es casi seguro incorrecto: asigna suficiente memoria para almacenar un 'char *', pero asigna un puntero que apunta a 'char' (y no hay necesidad de lanzar el retorno valor de 'malloc' en C, tampoco). 'str = malloc (N * sizeof * str);' es una mejor manera de escribir eso. – caf

+0

Como dijo CAF, nunca debe arrojar el valor de retorno de malloc(). Ver http://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the-result-of-malloc et al – Mawg

Respuesta

13

Tiene dos opciones: una, pasar un char * a alguna función y usar eso en lugar de asignar dentro de alguna función, o dos, liberar el valor de retorno más adelante.

La primera opción:

char *somefunction(char *str, int somearg){ 

    //some code 

    return str; 
} 

// Elsewhere... 
char *str = (char *) malloc....; 
somefunction(str, 123); 
// Code... 
free(str); 

La segunda opción:

char *somestr = somefunction(123); 
// Do something... 
free(somestr); 

Yo personalmente recomiendo la primera opción, ya que es un poco más fácil para evitar la memoria fugas cuando no está siendo asignado dentro de las funciones arbitrarias .

+1

Buena respuesta (y pregunta), me encontré con el mismo problema recientemente. Una pregunta: ¿qué pasa si es difícil determinar de antemano cuánta memoria necesita el valor de retorno de la función? Entonces parecería más natural asignar en la función; de lo contrario, necesitaría algún tipo de manejo de errores en la función para el caso de que el espacio de memoria suministrado sea demasiado pequeño (por ejemplo, para devolver una cadena de longitud variable). – sleske

+0

Una cadena de longitud variable podría justificar tener memoria asignada dentro de la función. Sin embargo, dudaría mucho sobre dicho código en mi propio proyecto, y preferiría especificar explícitamente una longitud máxima que se elige en función del contexto y los requisitos del código. ¿De qué tipo de cadenas de longitud variable estás hablando? ¿No podrían ser más de varios KB/MB que podrían ser preasignados? –

2

Debería liberar todo el espacio asignado, pero si lo devuelve porque usará ese espacio de memoria en otras partes del programa, entonces, después de usarlo, debería liberar. Vea cada lugar en el código que llama a la función y libere el espacio después de usar el valor devuelto.

2

Si desea devolver la dirección del bloque, no debe liberar() el bloque, sino que debe confiar en el código de llamada para liberarlo() más tarde. Esto se llama paso de onwership.

Si lo libera en la función y devuelve el puntero, el código de llamada se ejecutará en un comportamiento indefinido al intentar acceder al bloque ya liberado.

4

Lo liberas cuando terminas de usarlo. No hay ninguna regla que diga que el free() que coincide con un malloc() debe estar en la misma función.

+0

entonces, ¿podría hacer algo como free (str) fuera de la función o free (somefunction)? –

+1

Sí de hecho. Al igual que puede hacer con malloc(), que después de todo es solo otra función. –

2

Esta es una práctica para algunas funciones existentes (strdup(), por ejemplo) pero generalmente es una mala idea. Requerir que un usuario esté al tanto de lo que sucede dentro de una llamada a función es un mal requisito: piense en cuántas funciones usa y qué partes internas están ocultas para usted. En general, querrá tener un pase de usuario en un búfer y tamaño en lugar de asignar memoria para ellos.

+1

De acuerdo, pero ¿qué sucede si es difícil decidir de antemano cuánto espacio se necesitará (por ejemplo, crear dinámicamente una cadena para devolver). Entonces parecería más natural (y más simple) que la función asigne tanta memoria como necesite. ¿Qué piensas? – sleske

+0

Un muy buen punto. Sin embargo, en realidad, siempre habrá una longitud superior conocida para el aguijón, ya que tendrá que caber en un campo de base de datos, o en una pantalla o salida formateada. Por supuesto, es un desperdicio asignar 255 bytes cuando puede que solo necesite uno, por lo que depende de lo que esté implementando. No me preocuparía demasiado en una aplicación de Windows, pero un sistema integrado en un micro de 8 bits es una tetera diferente de caballos de colores. – Mawg

Cuestiones relacionadas