shampoo - Puntero colgante en C
remedios caseros para dar brillo a las canas (7)
Escribí un programa en C con un puntero colgante.
#include<stdio.h>
int *func(void)
{
int num;
num = 100;
return #
}
int func1(void)
{
int x,y,z;
scanf("%d %d",&y,&z);
x=y+z;
return x;
}
int main(void)
{
int *a = func();
int b;
b = func1();
printf("%d/n",*a);
return 0;
}
Estoy obteniendo la salida como 100 aunque el puntero esté colgando.
Hice un solo cambio en la función anterior func1()
. En lugar de tomar el valor de y
y z
de la entrada estándar como en el programa anterior, ahora estoy asignando el valor durante el tiempo de compilación.
func1()
el func1()
siguiente manera:
int func1(void)
{
int x,y,z;
y=100;
z=100;
x=y+z;
return x;
}
Ahora la salida es 200 .
¿Puede alguien por favor explicarme el motivo de los dos productos anteriores?
Con punteros colgantes, el resultado de un programa no está definido. Depende de cómo se usa la pila y los registros. Con diferentes compiladores, diferentes versiones de compiladores y diferentes configuraciones de optimización, obtendrá un comportamiento diferente.
Devolver un puntero a una variable local produce un comportamiento indefinido, lo que significa que cualquier cosa que haga el programa (cualquier cosa) es válida. Si está obteniendo el resultado esperado, eso es pura suerte.
Es por la forma en que se asigna la memoria.
Después de llamar a func
y devolver un puntero colgante, la parte de la pila donde se almacenó num
todavía tiene el valor 100
(que es lo que está viendo después). Podemos llegar a esa conclusión en función del comportamiento observado.
Después del cambio, parece que lo que ocurre es que la llamada func1
sobrescribe la ubicación de la memoria que apunta con el resultado de la adición dentro de func1
(el espacio de pila utilizado anteriormente para func
ahora es reutilizado por func1
), así que es por eso que ves 200.
Por supuesto, todo esto es un comportamiento indefinido, así que, aunque esta podría ser una buena pregunta filosófica, responderla realmente no te compra nada.
Es un comportamiento indefinido. Podría funcionar correctamente en su computadora en este momento, dentro de 20 minutos, podría colapsar en una hora, etc. Una vez que otro objeto ocupe el mismo lugar en la pila que num
, ¡estará condenado !
Los punteros colgantes (punteros a lugares que han sido desasociados) inducen un comportamiento indefinido , es decir, cualquier cosa puede suceder.
En particular, las ubicaciones de memoria se reutilizan por casualidad * en func1
. El resultado depende del diseño de la pila, la optimización del compilador, la arquitectura, las convenciones de llamadas y los mecanismos de seguridad de la pila.
Comportamiento indefinido significa que cualquier cosa puede suceder, incluido que hará lo que usted espera. Sus variables de pila no se sobrescribieron en este caso.
void func3() {
int a=0, b=1, c=2;
}
Si incluye una llamada a func3()
entre func1
y printf
, obtendrá un resultado diferente.
EDITAR: Lo que realmente sucede en algunas plataformas.
int *func(void)
{
int num;
num = 100;
return #
}
Supongamos, por simplicidad, que el puntero de pila es 10 antes de llamar a esta función y que la pila crece hacia arriba.
Cuando llama a la función, la dirección de retorno se empuja en la pila (en la posición 10) y el puntero de la pila se incrementa a 14 (sí, muy simplificado). La variable num entonces se crea en la pila en la posición 14, y el puntero de la pila se incrementa a 18.
Cuando regresa, devuelve un puntero a la dirección 14 - la dirección de retorno se saca de la pila y el puntero de la pila vuelve a 10.
void func2() {
int y = 1;
}
Aquí, pasa lo mismo. Dirección de retorno presionada en la posición, y creada en la posición 14, asigna 1 a y (escribe en la dirección 14), regresa y vuelve a colocar el puntero en la posición 10.
Ahora, su antiguo int *
regresó de los puntos func
a la dirección 14, y la última modificación realizada en esa dirección fue la asignación de variables locales de func2. Entonces, tienes un puntero colgante (nada sobre la posición 10 en la pila es válido) que apunta a un valor sobrante de la llamada a func2
Por favor estudie las funciones de C. básico. Su concepto es defectuoso ... main
debe ser
int main(void)
{
int *a = func();
int b;
b = func1();
printf("%d/n%d",*a,func1());
return 0;
}
Esto dará salida a 100 200