C “error: la función devuelve la dirección de la variable local”

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 me sale el siguiente error:

“error: la función devuelve la dirección de la variable local”, cualquier sugerencia, ¿cómo solucionar esto?

    Las variables locales tienen una duración que se extiende solo dentro del bloque en el que está definida. 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, usar la dirección de memoria de la variable fuera del área de tiempo de vida de la variable será un comportamiento indefinido. soy yo

    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 a 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 duración que abarca toda la ejecución del progtwig. Por lo tanto, puede acceder a la ubicación de la memoria desde cualquier bloque y en cualquier momento mientras se ejecuta el progtwig.

    También tenga en cuenta que, es una buena práctica que después de que haya terminado con el bloque de memoria asignado, free para guardarlo de memory leaks. Una vez que liberas la memoria, no puedes acceder a ese bloque nuevamente.

    PRÁCTICA:

    Actualmente estoy enseñando a un amigo los conceptos básicos de C, y se me ocurrió este ejemplo de código muy simple y directo (eso espero) que básicamente explica todo. ¡No quería esconderlo de ustedes! 🙂

     #include  #include  #include  /* 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 comstackrlo, obtienes la advertencia [intencionada]:

     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í!

    ejecutar mi ejemplo produce esta salida:

     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 piense de esta manera: todo lo que está entre { y } es el scope local , por lo tanto, el C-Standard está "indefinido" afuera. Al usar malloc, toma la memoria del HEAP (scope del progtwig) y no de la PILA (scope de la función), por lo tanto, es "visible" desde el exterior. La segunda forma correcta de hacerlo es llamada por referencia . Aquí define la var dentro del objeto principal, por lo tanto, está utilizando la stack (porque el ámbito principal es main () ).

    RESUMEN:

    3 maneras de hacerlo, uno de ellos falso. C es una especie de torpe para simplemente tener una función devolver una cadena de tamaño dynamic. O tiene que malloc y luego liberarlo, o tiene que llamar por referencia. O use C ++;)

    Esta línea:

     char b = "blah"; 

    No es bueno, tu lvalue debe ser un puntero.

    Su código también está en peligro de un desbordamiento de stack, ya que su verificación de recursión no está limitando 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; el momento en que return dejará de existir. Necesita algo más que una variable automática.

    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.

    Usando 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; } 

    a es una matriz local para la función. Una vez que la función retorna ya no existe y, por lo tanto, no debe devolver la dirección de una variable local.
    En otras palabras, el tiempo de vida de a está dentro del scope ( { , } ) 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. Estas variables también se denominan variabels automáticos porque su duración se gestiona automáticamente, no es necesario que lo administre explícitamente.

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

     char *a = malloc(1000); 

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

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

     char *a = malloc(1000); 

    Y en algún momento, llame free al puntero devuelto.

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

     char b = "blah"; 

    debiera ser:

     char *b = "blah";