Devuelve un puntero que apunta a una variable local

No sé por qué esto funciona. Como x es una variable local, pensé que obtendría un error cuando intentara devolverlo. Sin embargo, el primer printf funciona bien, pero luego imprime 0. ¿Alguien puede explicar qué está pasando aquí?

#include  int* func1() { int x = 123123; int *y = &x; return y; } int main() { int* c = func1(); printf("%d\n", *c); // output: 123123 printf("%d\n", *c); // output: 0 return 0; } 

Sucede lo siguiente:

  1. Dentro de func1 , creó la variable x local y la inicializó con un valor, es decir, x está en la stack.
  2. Obtienes la dirección de x y la devuelves a main .
  3. Al regresar, func1 y sus variables x (y, irrelevantes para la pregunta, y ) están free d, o saltadas de la stack, es decir, sus ubicaciones de memoria ya no están reservadas para mantener sus valores. Después de esto, cualquier otra parte del progtwig puede usar el espacio de memoria asignado para x dentro de func1 , ya que func1 ya no está activo.
  4. Su primera llamada a printf sigue viendo el antiguo valor de la ubicación de memoria donde solía estar x (pero esto no está garantizado) y
  5. la segunda llamada a printf hace evidente que otra cosa (con el valor de 0, como el valor de retorno de la primera printf como lo describe R. Joiny ) está (o estaba) usando la misma dirección que x dentro de func1 .

Este artículo del Boot Camp de Progtwigción en C describe bastante a su situación:

Una clave para entender la stack es la noción de que cuando una función sale, todas sus variables se desprenden de la stack (y, por lo tanto, se pierden para siempre). Por lo tanto, las variables de la stack son de naturaleza local. Esto se relaciona con un concepto que vimos anteriormente conocido como variable scope, o variables locales vs globales. Un error común en la progtwigción de C es intentar acceder a una variable que se creó en la stack dentro de alguna función, desde un lugar en su progtwig fuera de esa función (es decir, después de que esa función haya salido).

printf es básicamente una función. Como tu func1 .

Las funciones usan algo de RAM, su espacio de trabajo para variables locales. Si abandona la función, se considera como algo así como “claro para usar” (¡no se elimina!).

Debido a que el primer printf() viene directamente después de la función func1() , la variable local C todavía está allí, porque aún no se ha sobrescrito. Así que eso funciona. Pero si observa esta página MAN , puede ver que printf tiene int como valor de retorno. Entonces, eso tiene que escribirse en algún lugar, entonces, ¿qué haría tu PC? Por supuesto, escríbalo a la primera dirección libre de la memoria RAM, que se asigna a su progtwig. Y ahí tienes tu cero.

Es importante tener en cuenta que ningún otro progtwig puede acceder a su RAM, Windows reserva automáticamente la RAM para cada proceso, por lo que debe ser el valor de retorno de printf() (o alguna otra variable local que printf usa durante la ejecución).

Como x es una variable local, pensé que obtendría un error cuando intentara devolverlo.

Una respuesta más general a este problema es: el código incorrecto en el código C no produce necesariamente un error de comstackción o de tiempo de ejecución.

Si tienes mucha suerte, obtendrás un error o advertencia del comstackdor.

Si tiene suerte, obtendrá un locking de tiempo de ejecución cuando se ejecuta el código incorrecto (esto suele suceder con errores de puntero nulo). Esto es fácil de localizar con un depurador.

Pero si no tiene suerte, el código incorrecto puede causar lockings posteriores (en código aparentemente no relacionado), o corromper silenciosamente algunas estructuras de datos (haciendo que su progtwig se comporte de formas extrañas sin fallar), o incluso parecer que funciona bien (hasta que agregue código aparentemente inofensivo en otra parte, o use un comstackdor diferente, o una versión diferente del mismo comstackdor, o simplemente diferentes opciones de comstackción).


Técnicamente su código tiene un comportamiento indefinido en esta línea:

 int* c = func1(); 

Estás usando el valor de retorno de func1 (escribiéndolo en c ). Pero ese valor es la dirección de una variable local en func1 , que ya no existe en el momento en que ha devuelto func . Eso significa que el valor de retorno es un puntero no válido, y el uso de dicho puntero conduce a un comportamiento indefinido (ni siquiera tiene que desreferenciarlo).

 printf("%d\n", *c); // output: 123123 

Bueno, esta línea usa el puntero malo (leyéndolo de c ) y lo desactualiza. El progtwig todavía parece funcionar bien.

 printf("%d\n", *c); // output: 0 

Una adición aparentemente inofensiva, pero esta línea no produce el resultado esperado. Ahora parece que la corrupción de datos en silencio.

Tenga en cuenta que nada de esto está garantizado. Un comstackdor diferente o el mismo comstackdor que usa configuraciones de optimización diferentes pueden producir código que se comporte de manera diferente. En lo que respecta a la norma, un comstackdor tiene que producir un código que coincida con el comportamiento observable del código C. Pero el código C cuyo comportamiento no está definido puede hacer que suceda cualquier cosa; No hay garantías o restricciones sobre lo que el comstackdor puede hacer con él.