como - cadena de retorno de la función sin malloc
malloc sizeof (7)
Depende.
Podría decidir y documentar que la cadena devuelta es un puntero a algún búfer interno estático. Entonces su rutina no es re-entrante (ni segura para subprocesos). Por ejemplo, getpwent
o getpwent
hace eso.
Una cosa mejor sería pasar la cadena y el tamaño del resultado como argumentos, y rellenar esa cadena y posiblemente devolverla. getcwd
(o snprintf
o strftime
que devuelve un tamaño, no un puntero) funciona de esa manera.
Pero, por lo general, usted decide y documenta que la cadena devuelta está asignada a un montón, y es responsabilidad del llamante free
. Es posible que desee utilizar strdup
o asprintf
en ese caso.
Y podría usar en todo su programa el recolector de basura conservador de Boehm (por ejemplo, use su GC_STRDUP
o GC_MALLOC_ATOMIC
para cadenas, y GC_MALLOC
para valores de pila que contienen algunos punteros).
Si considera que malloc
o strdup
estándar es demasiado lento (pero mida eso primero), podría tener sus propios asignadores de grupo, etc.
También puede tener esquemas alternativos (pero es importante documentarlos). Por ejemplo, puede devolver alguna cadena internada , o incluso una cadena internada canónica (a veces llamada "quark" o "símbolo"), y luego usar la igualdad de puntero en lugar de la igualdad de cadena. También podría tener algún esquema de contador de referencia . Mire, por ejemplo, lo que Glib (de GTK, pero que se puede utilizar fuera de los programas GUI) proporciona: GString-s , GQuark-s , utilidades de cadena
Sin embargo, es importante decidir si el resultado se asigna o no al montón, y definir claramente quién tiene la responsabilidad de liberar (y cómo debe ser liberado) el resultado asignado por el montón.
Es posible que desee utilizar valgrind para perseguir las fugas de memoria. ¡No olvides pasar -Wall -g
a tu compilador gcc
!
PD. Consideraría usar el GC de Boehm. Y no creo que se deba rechazar malloc
(o strdup
, asprintf
....) por razones de rendimiento (puede elegir otra implementación de malloc
más rápida o usar sus propios pools de memoria). Sin embargo, las fugas de memoria pueden ser un problema.
¿Es posible devolver una cadena desde una función sin llamar a malloc
? Tengo una función como la siguiente:
char* getString(){
char tempStr[20]
// open file, read char by char and assign to tempStr
// ....
char* str = (char*)malloc(sizeof(char)*20);
strcpy(str, tempStr); // assume this copy the null terminating char as well
return str;
}
Y luego, cuando llamo a getString()
, asigno el valor de retorno a un char*
, y luego lo libero cuando termine, como a continuación:
void randomFunction(){
char* line = NULL;
int i = 0;
while (i < 1000) {
line = getString();
// do stuff with line
free (line);
line = NULL;
}
}
Sin embargo, me pregunto si hay alguna manera de hacer esto sin malloc
? Y, ¿es esta la forma correcta de devolver una cadena desde una función en C? Intenté investigar un poco sobre cómo regresar sin malloc
, pero no encontré respuestas claras. Soy nuevo en C y todavía estoy aprendiendo.
Hay tres formas comunes de devolver una cadena desde una función. (Bueno, en realidad no hay ninguno, pero hay tres formas comunes de devolver un puntero a una cadena, que la persona que llama puede usar para acceder a la cadena).
Asigne espacio para la cadena usando
malloc()
dentro de la función. Este es el método más flexible, pero hace que la persona que llama sea responsable defree()
la matriz asignada. También puede imponer alguna sobrecarga de rendimiento.Requerir que la persona que llama asigne espacio para la cadena y pase un puntero a ese espacio. Esto impone algunos inconvenientes a la persona que llama. En particular, la persona que llama tiene que decidir qué tan grande puede ser la cadena.
Devuelva un puntero a (el primer elemento de) una matriz
static
definida dentro de la función. La matriz continuará existiendo después de que la función regrese, pero solo hay una copia, lo que significa que las llamadas sucesivas afectarán el resultado devuelto por las llamadas anteriores. También significa que la matriz debe ser de un tamaño fijo, que se debe elegir al escribir el código.
La forma normal de mover la asignación de memoria fuera de una función es pasar punteros. Aunque en la práctica querrás asegurarte de no pasar por los límites del búfer también.
char* getString(char* tempStr){
// open file, read char by char and assign to tempStr
// ....
return tempStr;
}
void randomFunction(){
char line[20];
int i = 0;
while (i < 1000) {
getString(line);
// do stuff with line
}
}
No puede devolver un carácter temporal desde una función y, a menos que use un malloc, la matriz de caracteres definida en la función será temporal. Una solución alternativa es pasar una matriz de caracteres como parámetro a la función y usarla como parámetro de salida.
Simplemente declare la cadena como estática en la función y devuélvala.
Una forma común de hacer esto en C es tener la cadena pasada como un argumento a la función.
char *getString(char *str, int size){
// open file, read char by char and assign to tempStr
// ....
strncpy(str, tempStr, size); // assume this copies the null terminator
return str;
}
Alternativamente, puede hacer que la cadena se declare estática, o en un archivo o ámbito global, y copiarla en ella. Sin embargo, asegúrese de que si guarda un puntero a un búfer asignado en el montón en este símbolo, lo libere antes de volver a asignarlo.
Ya que su cadena tiene (aparentemente) siempre 20 caracteres, simplemente puede hacer esto:
void getString( char *outputString ) {
// do stuff to outputString instead of mallocing, or use local memory and copy it at the end
}
char line[20];
for( ... ) {
getString( line );
// do things with line
}
Debido a que esto evita muchos mallocs pequeños, es más rápido.