visual variable una que locales globales ejemplo constantes c return strcpy strcat

una - variables locales en c



error: la función devuelve la dirección de la variable local (7)

Soy principiante con C y estoy aprendiendo por mi cuenta. Estoy creando la siguiente función:

char *foo(int x){ if(x < 0){ char a[1000]; char b = "blah"; x = x - 1; char *c = foo(x); strcpy(a, b); strcat(a, c); return a; } blah ... }

Básicamente estoy tratando de devolver una cadena anexada, pero recibo el siguiente error:

"error: la función devuelve la dirección de la variable local", alguna sugerencia, ¿cómo solucionarlo?


Esta línea:

char b = "blah";

No es bueno, tu valor lime debe ser un indicador.

Su código también está en peligro de desbordamiento de pila, ya que su comprobación de recursión no limita el valor decreciente de x.

De todos modos, el mensaje de error real que está recibiendo es porque char a es una variable automática; En el momento en que return dejará de existir. Necesitas algo más que una variable automática.


Las variables locales tienen un tiempo de vida que se extiende solo dentro del bloque en el que se define. En el momento en que el control sale del bloque en el que se define la variable local, el almacenamiento de la variable ya no está asignado (no está garantizado). Por lo tanto, el uso de la dirección de memoria de la variable fuera del área de vida de la variable será un comportamiento indefinido.

Por otro lado puedes hacer lo siguiente.

char *str_to_ret = malloc (sizeof (char) * required_size); . . . return str_to_ret;

Y usa el str_to_ret en str_to_ret lugar. Y al return ing str_to_ret , se str_to_ret la dirección asignada por malloc . La memoria asignada por malloc se asigna desde el montón, que tiene una vida útil que abarca toda la ejecución del programa. Por lo tanto, puede acceder a la ubicación de la memoria desde cualquier bloque y en cualquier momento mientras el programa se está ejecutando.

También tenga en cuenta que es una buena práctica que, una vez que haya terminado con el bloque de memoria asignado, free para evitar pérdidas de memoria. Una vez que liberas la memoria, no puedes volver a acceder a ese bloque.


Ni malloc ni llamada por referencia son necesarios. Puede declarar un puntero dentro de la función y establecerlo en la cadena / matriz que desea devolver.

Utilizando el código de @Gewure como base:

char *getStringNoMalloc(void){ char string[100] = {}; char *s_ptr = string; strcat(string, "bla"); strcat(string, "/"); strcat(string, "blub"); //INSIDE this function "string" is OK printf("string : ''%s''/n", string); return s_ptr; }

funciona perfectamente.

Con una versión sin bucle del código en la pregunta original:

char *foo(int x){ char a[1000]; char *a_ptr = a; char *b = "blah"; strcpy(a, b); return a_ptr; }


Se me ocurrió este ejemplo de código simple y directo (eso espero) que debería explicarse por sí mismo.

#include <string.h> #include <stdio.h> #include <stdlib.h> /* function header definitions */ char* getString(); //<- with malloc (good practice) char * getStringNoMalloc(); //<- without malloc (fails! don''t do this!) void getStringCallByRef(char* reference); //<- callbyref (good practice) /* the main */ int main(int argc, char*argv[]) { //######### calling with malloc char * a = getString(); printf("MALLOC ### a = %s /n", a); free(a); //######### calling without malloc char * b = getStringNoMalloc(); printf("NO MALLOC ### b = %s /n", b); //this doesnt work, question to yourself: WHY? //HINT: the warning says that a local reference is returned. ??! //NO free here! //######### call-by-reference char c[100]; getStringCallByRef(c); printf("CALLBYREF ### c = %s /n", c); return 0; } //WITH malloc char* getString() { char * string; string = malloc(sizeof(char)*100); strcat(string, "bla"); strcat(string, "/"); strcat(string, "blub"); printf("string : ''%s''/n", string); return string; } //WITHOUT malloc (watch how it does not work this time) char* getStringNoMalloc() { char string[100] = {}; strcat(string, "bla"); strcat(string, "/"); strcat(string, "blub"); //INSIDE this function "string" is OK printf("string : ''%s''/n", string); return string; //but after returning.. it is NULL? :) } // ..and the call-by-reference way to do it (prefered) void getStringCallByRef(char* reference) { strcat(reference, "bla"); strcat(reference, "/"); strcat(reference, "blub"); //INSIDE this function "string" is OK printf("string : ''%s''/n", reference); //OUTSIDE it is also OK because we hand over a reference defined in MAIN // and not defined in this scope (local), which is destroyed after the function finished }

Al compilarlo, aparece la advertencia [prevista]:

me@box:~$ gcc -o example.o example.c example.c: In function ‘getStringNoMalloc’: example.c:58:16: warning: function returns address of local variable [-Wreturn-local-addr] return string; //but after returning.. it is NULL? :) ^~~~~~

... básicamente lo que estamos discutiendo aquí!

Al ejecutar mi ejemplo se obtiene este resultado:

me@box:~$ ./example.o string : ''bla/blub'' MALLOC ### a = bla/blub string : ''bla/blub'' NO MALLOC ### b = (null) string : ''bla/blub'' CALLBYREF ### c = bla/blub

Teoría:

Esto ha sido respondido muy bien por el usuario @phoxis. Básicamente, piénselo de esta manera: todo lo que se encuentre entre { y } es de alcance local , por lo que el estándar C está fuera "indefinido". Al utilizar malloc, se toma la memoria del HEAP (alcance del programa) y no del STACK (alcance de la función), por lo tanto, es "visible" desde el exterior. La segunda forma correcta de hacerlo es llamada por referencia . Aquí se define la var dentro del ámbito principal, por lo tanto, está utilizando la APILACIÓN (porque el ámbito principal es el principal () ).

Resumen:

3 maneras de hacerlo, una de ellas falsa. C es un tanto torpe como para que una función devuelva una cadena de tamaño dinámico. O bien tiene que realizar una operación de malloc y luego liberarla, o debe llamar por referencia. O utilice C ++;)


a es una matriz local de la función. Una vez que la función devuelve ya no existe y, por lo tanto, no debe devolver la dirección de una variable local.
En otras palabras, la vida útil de a está dentro del alcance ( { , } ) de la función y si le devuelve un puntero, lo que tiene es un puntero que apunta a alguna memoria que no es válida. Dichas variables también se denominan variables automáticas porque su vida útil se gestiona automáticamente, no es necesario que las gestione explícitamente.

Dado que necesita extender la variable para persistir más allá del alcance de la función, debe asignar una matriz en el montón y devolverle un puntero.

char *a = malloc(1000);

De esta manera, la matriz a reside en la memoria hasta que llame a free() en la misma dirección.
No olvides hacerlo o terminarás con una pérdida de memoria.


a se define localmente en la función y no se puede utilizar fuera de la función. Si desea devolver una matriz de caracteres desde la función, deberá asignarla dinámicamente:

char *a = malloc(1000);

Y en algún punto llamar free en el puntero devuelto.

También debería ver una advertencia en esta línea: char b = "blah"; : estás intentando asignar una cadena literal a un char .


char b = "blah";

debiera ser:

char *b = "blah";