Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: ghastlyX en 10 Agosto 2013, 01:10 am



Título: Comportamiento extraño de g++
Publicado por: ghastlyX en 10 Agosto 2013, 01:10 am
Hola a todos,

El otro día estaba programando un cierto código con árboles y cuando compilaba el programa se comportaba de forma que no conseguía entender. Para no poner el código original, he simplificado el código lo máximo posible para que se vea el comportamiento con el código tan corto y simple como sea posible.

Ante todo, para no ir repitiéndome, comento que la entrada (vía stdin) que utilizo en los códigos que voy a poner es la string 110.

El primer código es el siguiente, que se comporta como yo esperaría:
Código
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef vector<int> VI;
  7.  
  8. VI fe;
  9.  
  10. int llegeix() {
  11.  char c;
  12.  cin >> c;
  13.  if (c == '0') return -1;
  14.  
  15.  int u = fe.size();
  16.  fe.push_back(42);
  17.  
  18.  int aux = llegeix();
  19.  fe[u] = aux;
  20.  
  21.  return u;
  22. }
  23.  
  24. int main() {
  25.  
  26.  llegeix();
  27.  
  28.  for (int i = 0; i < fe.size(); ++i) cerr << fe[i] << endl;
  29. }

La función llegeix (que para que tenga sentido, significa lee en catalán), simplemente guarda en el vector fe la posición del siguiente 1 leído o -1 si se lee un cero (caso en el que para).

Naturalmente, el programa imprime lo siguiente, que es correcto.
Código:
1
-1

Y aquí viene el juego de manos que convierte este código en la versión que manifiesta el comportamiento que no entiendo. Simplemente comento la línea 18 y asigno directamente al vector lo que devuelve la función:
Código
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef vector<int> VI;
  7.  
  8. VI fe;
  9.  
  10. int llegeix() {
  11.  char c;
  12.  cin >> c;
  13.  if (c == '0') return -1;
  14.  
  15.  int u = fe.size();
  16.  fe.push_back(42);
  17.  
  18.  //int aux = llegeix();
  19.  fe[u] = llegeix();
  20.  
  21.  return u;
  22. }
  23.  
  24. int main() {
  25.  
  26.  llegeix();
  27.  
  28.  for (int i = 0; i < fe.size(); ++i) cerr << fe[i] << endl;
  29. }

En mi ordenador, con esta versión de g++:
Código:
alex@portatil:~$ g++ --version
g++ (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Da la siguiente salida, diferente del código anterior, por motivos que no entiendo:
Código:
42
-1

He comprobado el código en IdeOne con la versión 4.8.1 que tienen actualmente y ambos códigos me dan los mismos resultados que en mi ordenador. A mi entender, dichos códigos deberían comportarse de la misma forma, ya que si bien la función recursiva modifica el vector (añade un elemento), la variable u no se ve modificada y es diferente en cada llamada de la función.

Para colmo, un amigo con Windows y Dev-C++, que creo que lleva una versión bastante antigua de g++, me dijo que al compilarlos ambos códigos daban la salida que me da a mí el primer código, es decir, la correcta.

Sinceramente no entiendo por qué ambos códigos dan resultados distintos y lo más curioso es que si el 42 que he puesto por poner algo se cambia por cualquier otro número en el segundo código, la salida del primer elemento del vector será dicho número, como si la asignación del primer elemento no se hiciera nunca.

¿Alguien puede decirme el motivo de este comportamiento?

Muchas gracias


Título: Re: Comportamiento extraño de g++
Publicado por: do-while en 10 Agosto 2013, 15:30 pm
¡Buenas!

LALALALALA (No he dicho nada mas que tonterias....). Lo siento. Ahora lo miro mejor.

¡Saludos!

a ver
Código:

int fun

leer c;
si c== '0'
    fun = -1

tamaño = longitud.vector;
insertar 42 //ahora vector[tamaño] es c

aux = fun
vector[tamaño] = aux // vector[tamaño] = -1 o el tamaño actual + 1
//en el ultimo paso sobreescribo el valor 42...

devolver tamaño...

Por lo tanto, tu funcion rellena el vector con valores 1,2,3,...,n,-1 ¿No?

Y el programa revienta... ¿¿¿??? No lo veo...

 :o :o :o :o

Es verdad. Si utilizo la variable aux, todo va bien, pero en cuando utilizo el valor devuelto por la función, el programa se va a tomar viento fresco...

No se porque pasa...


Título: Re: Comportamiento extraño de g++
Publicado por: ghastlyX en 10 Agosto 2013, 15:58 pm
Bueno, con la entrada 110, el programa sin la variable auxiliar no es que pete, simplemente no cambia el valor del primer elemento del vector.

Yo tampoco tengo ni la menor idea de por qué pasa esto, más cuando un amigo me comentó que con Dev-C++ los dos códigos dan el mismo valor.


Título: Re: Comportamiento extraño de g++
Publicado por: do-while en 10 Agosto 2013, 16:05 pm
Yo estoy con CodeBlocks, utilizando mingw (la última version (o por lo menos la que había para descargar hace un par de meses como mucho), y me peta si asigno directamente el valor que devuelve la función. He probado a cambiar [] por at, por probar algo, pero sigue reventando...

¿Algún aficionado a los debugers que pueda ilustrarnos?


Título: Re: Comportamiento extraño de g++
Publicado por: leogtz en 10 Agosto 2013, 19:08 pm
Quizás son problemas de limpia de stdin, cambia el comportamiento con lo siguiente:

Código
  1. #include <iostream>
  2. #include <vector>
  3. #include <limits>
  4. #include <cstdio>
  5. using namespace std;
  6.  
  7. typedef long long ll;
  8. typedef vector<int> VI;
  9.  
  10. VI fe;
  11.  
  12. void view() {
  13.    for(std::vector<int>::size_type i = 0; i != fe.size(); i++)
  14.        std::cout << fe[i] << " ";
  15. }
  16.  
  17. int llegeix() {
  18.  
  19.  std::cout << std::endl;
  20.  char c;
  21.  cin >> c;
  22.  
  23.  while((c = getchar()) != '\n' && c != EOF);
  24.  
  25.  if (c == '0') return -1;
  26.  
  27.  int u = fe.size();
  28.  fe.push_back(42);
  29.  
  30.  //int aux = llegeix();
  31.  //std::cout << "Ahora hay: " << fe.size() << std::endl;
  32.  view();
  33.  
  34.  fe[u] = llegeix();
  35.  
  36.  return u;
  37. }
  38.  
  39. int main() {
  40.  
  41.  llegeix();
  42.  
  43.  for (int i = 0; i < fe.size(); ++i) cerr << fe[i] << endl;
  44. }
  45.