una programacion programa pilas pila metodo estatica eliminar elemento ejemplos dinamica dev como colas codigo ats c++ compiler-construction sample stackunderflow

programacion - Aprendizaje de C++: ejemplo de Underflow de pila en C++



programa de pilas en dev c++ (4)

Lo que puede ser un simple ejemplo en C ++ que causa una acumulación de subdesbordamiento en el caso de invocación y devolución de llamadas a métodos. Estoy familiarizado con la convención de llamadas, es decir, con esta llamada, stdcall y cdecl y la forma en que limpiarían la pila. En específico, ¿No se ocuparía el desbordamiento de la pila del código generado automáticamente por el compilador?

¿Cuáles son las situaciones que pueden meterme en problemas con stack-underflow?


La única forma en que puedo ver que esto realmente sucede sería si declaraste una función para usar stdcall (o cualquier otra convención de llamadas que especifique que el callee limpia la pila) y luego invocas la función a través de un puntero de función que se especificó como cdecl ( o cualquier otra convención de llamadas donde la persona que llama limpia la pila). Si haces eso, la función llamada abrirá la pila antes de regresar y luego la persona que llama también abrirá la pila y se perderán cosas terribles.

En el caso específico de las funciones de miembro, la convención de llamada se conoce generalmente como esta thiscall y si la persona que llama o quien llama limpia la pila depende del compilador.

Consulte aquí para obtener detalles sobre las convenciones de llamadas.


No estoy seguro si está hablando de la pila de estructura de datos y el problema de subdesbordamiento en ella o algo más. En lo que se refiere al problema de stack(data structure) underflow la stack(data structure) underflow aquí hay una explicación.

stack es un tipo de datos abstractos de entrada y salida (LIFO) y una estructura de datos. Una pila puede tener cualquier tipo de datos abstractos como un elemento, pero se caracteriza por solo tres operaciones fundamentales: push , pop y stack top .

La operación de inserción agrega un nuevo elemento a la parte superior de la pila o inicializa la pila si está vacía. Si la pila está llena y no contiene espacio suficiente para aceptar el elemento dado, entonces se considera que la pila está en un estado de desbordamiento. La operación pop elimina un elemento de la parte superior de la pila.

Un pop revela elementos previamente ocultos, o resulta en una pila vacía, pero si la pila está vacía, entra en un estado de subdesbordamiento (significa que no hay elementos en la pila para eliminar).

La operación de pila superior obtiene los datos de la posición superior y los devuelve al usuario sin eliminarlos. El mismo estado de subdesbordamiento también puede ocurrir en la operación de pila superior si la pila está vacía.

Considere un ejemplo de implementación de pila:

template <class Item> class Stack { public: bool isEmpty() const; size_t size() const; Item pop(); void push(const Item& it); private: };

Ahora considere las siguientes operaciones que se realizan en esta pila.

C++ command resulting stack ------------------------------------------------ Stack<int> S; _____ (empty stack of ints) S.push(7); | 7 | <-- top ----- S.push(2); | 2 | <-- top | 7 | ----- S.push(73); |73 | <-- top | 2 | | 7 | ----- S.pop(); | 2 | <-- top | 7 | ----- S.pop(); ----- S.pop(); | 7 | <-- top ----- S.pop(); ----- (empty) S.pop(); ERROR "stack underflow"


Normalmente esto sería atendido por el compilador. En realidad, la única forma en que puedo pensar que accidentalmente podría causar un subdesbordamiento de la pila sería llamando a un método implementado con una convención de llamadas como si estuviera usando otra convención de llamadas.


Si alguna vez estás en una posición donde podría ocurrir un flujo insuficiente de la pila de llamadas, es probable que tu programa sufra una muerte violenta antes de que suceda. Al menos, si entiendo cómo funciona la función de llamadas es precisa.

Básicamente, la única forma de que suceda es si llama a una función donde el destinatario limpia la pila, y aparece demasiados valores ... si la persona que llama cree que una función acepta dos parámetros, pero el destinatario realmente toma tres, esto podría suceder. Una variante sería una función en la que el destinatario borra la pila, y luego la persona que llama limpia la pila nuevamente, como podría suceder si su convención de llamadas se equivoca. En ambas situaciones, es probable que tengas un problema cuando vas a vincular y los nombres destrozados son incorrectos, pero tal vez simplemente tengas muy mala suerte.

De cualquier manera, lo importante es que después de la llamada a la función, la pila es uno o más bytes más cortos de lo que se supone que debe ser. En teoría, el programa continuará, eliminando la cantidad correcta de datos, pero quedando uno o más bytes por debajo de lo esperado. Eventualmente, no hay más datos que explotar, y usted tiene un subdesbordamiento de pila.

Sin embargo, cuando se refiere a la pila, las direcciones son relativas a la parte superior. Entonces el compilador buscará un objeto particular en [la parte superior de la pila + 3] si está a tres bytes de la parte superior de la pila. Todavía lo hará si la pila termina más corta de lo esperado, y busca ese objeto en la ubicación incorrecta. Suponiendo que el objeto aún está allí ... podría haber salido accidentalmente ya. Cuando llegas al final de cualquier función en la que te encuentres, es posible que no pueda encontrar la dirección de retorno correcta por la misma razón, pero incluso si lo hace, tener todos tus objetos de repente corruptos es una situación bastante grave para estar en .

Advertencia: todo esto se basa en la suposición de que los sistemas modernos se comportan igual que los antiguos microcontroladores en los que solía trabajar hace una década. Quizás sean más inteligentes que eso ahora.