Por Ej:¿Es una buena práctica devolver el puntero de la función en c?
int *point() {
int *q = malloc(sizeof(int));
*q=20;
return q;
}
int main() {
int *a = point();
free(a);
}
Me pregunto si esto es una buena práctica en c?
Por Ej:¿Es una buena práctica devolver el puntero de la función en c?
int *point() {
int *q = malloc(sizeof(int));
*q=20;
return q;
}
int main() {
int *a = point();
free(a);
}
Me pregunto si esto es una buena práctica en c?
Devolver punteros es bastante común. El problema, o la disciplina necesaria, es estar seguro de dónde radica la responsabilidad de liberar la memoria. Este ejemplo huele porque no está claro que haya que liberarlo en main().
Corrección: Está claro de todo el ejemplo del código, pero si un usuario de la API no tuviera acceso al código para 'point()' no estaría claro. Cuando una función devuelve un puntero, documente si necesita ser 'free()' -d (o si es necesario, se debe usar una limpieza más especializada). –
Sí, es fácil cuando la función está justo frente a usted. No es tan fácil cuando está enterrado en una biblioteca de 10,000 líneas. :) – DGM
Creo que el problema es el libre (a); Creo que deberías agregar una función release_point().
No estoy de acuerdo. Si se requiere más limpieza que 'free()', entonces sí, agregue una función de destructor. Pero si su función de limpieza no es más que 'void release (mytype * p) {free (p); } 'entonces su función de limpieza es un poco innecesaria. Puede documentar que cualquiera que use su tipo de datos necesita llamar 'free()' tan fácilmente como puede documentar que deben llamar a su función personalizada de liberación/destrucción. Además, todos saben lo que 'libre()' hace. –
@Chris: Tener una función release_point() aseguraría que, si se necesitara una limpieza en el futuro, no se requiere la refacturación de la aplicación completa. –
de acuerdo, pero punto debe llamarse algo así como create_point(). De esa forma, me hace pensar inmediatamente que debería destruir el punto más tarde. –
Consulte el ejemplo C en el wikipedia page for opaque pointers. Es una forma de estructurar el código donde usted maneja la memoria completamente en un lado de la interfaz.
Si tiene un sistema consistente para saber qué funciones devuelven los punteros que deben liberarse (como usar la palabra create
o new
en el nombre de la función), entonces es más fácil administrar su memoria.
int *createPoint()
{
int *q = malloc(sizeof(int));
if (*q)
*q = 20;
return q;
}
El único peligro real que conozco con devolviendo un puntero a la memoria asignada es la siguiente: si la biblioteca se compila en Windows y vinculado a una instancia de la biblioteca de C++ Visual tiempo de ejecución (MSVCRT), por ejemplo, está vinculado estáticamente a él, y un programa cliente está vinculado a otra instancia, por ejemplo, está vinculado a la DLL, entonces cada uno tiene una arena malloc diferente, y los punteros devueltos por la biblioteca no pueden ser liberados por el programa. Cualquier intento de hacerlo puede causar la falla del programa.
Yo recomendaría tener siempre tu propia función para liberar la memoria que devuelve tu biblioteca, a menos que devuelvas algo trivial como una cadena.
La razón de esto es que, si cambia la estructura de lo que está devolviendo, un simple free
ya no será suficiente (porque agrega a los punteros de objetos devueltos a la memoria asignada que necesitan ser liberados) , los clientes no necesitarán cambiar su código; simplemente puede cambiar su función gratuita existente.
Por lo tanto, tener su propia función libre aísla a los clientes de la estructura de los objetos devueltos por su biblioteca, permitiéndole cambiar la estructura de sus objetos sin afectar a los clientes.
A menudo es una buena práctica, pero su ejemplo es uno de los pocos casos en que es una muy mala práctica. Nunca debe utilizar asignaciones dinámicas y punteros para objetos individuales que son pequeños y no contienen (y nunca deberán contener) punteros. Obtener un byte int
de 4 bytes con malloc
utiliza al menos 16 bytes una vez que tenga en cuenta la sobrecarga de contabilidad, pero quizás mucho más importante, significa que tiene que preocuparse por posibles fallas de asignación (y cómo manejarlas) y administrar cuándo liberar el objeto .
Algunos ejemplos de objetos que no se debe asignación de esta manera:
Por supuesto, la única vez que podría tener sentido para asignar y devolver un puntero a tales objetos es cuando estás asignando un matriz de ellos.
Según las respuestas actuales, esta es una pregunta claramente subjetiva. No parece haber criterios objetivos para determinar la bondad o la maldad de esta práctica de codificación, y existen argumentos a favor y en contra de ella. –
@Mark: eso es una tontería. Por supuesto, hay argumentos a favor y en contra de devolver un puntero, pero eso se debe a que es * a veces * algo sensato que hacer, y otras no. Una buena respuesta, ya que parece estar en duda, sería sobre eso explica * cuando * es una buena práctica devolver un puntero, y * por qué * es/no es. – jalf
Y la próxima vez que decida votar para que se cierre una pregunta, le sugiero que lea la razón detallada antes de hacer clic en ella. El motivo cercano no dice "subjetivo". Dice "subjetivo y argumentativo". Es la parte "argumentativa" lo que es realmente importante. Nadie quiere una guerra de llamas, después de todo. Pero esta pregunta, como muchas otras preguntas subjetivas, puede ser respondida objetivamente. La respuesta de @ DGM, por ejemplo, es objetiva. Hace una observación sobre cuán comúnmente se hace esto, explica cómo se deben hacer los punteros de retorno, y explica cuál es el problema con el ejemplo del PO. – jalf