Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Extraño caso al evaluar una condición. (https://www.clubdelphi.com/foros/showthread.php?t=85678)

pacopenin 16-04-2014 19:21:22

Extraño caso al evaluar una condición.
 
Hola a todos.
No se si le ha pasado a alguien pero a mi me ha pasado en dos o tres proyectos distintos y con distintas versiones de Delphi (2, 6 y ahora con 2007). No se porque ocurre pero de vez en cuando pasa. En esta ocasión es al evaluar un if, que según se ve en la ventana de depuración la condición devuelve falso y está ejecutando las instrucciones correspondientes al valor verdadero.
Lo pongo no para buscar una solución, sino como curiosidad ya que como digo, me ha pasado alguna vez más.


nlsgarcia 16-04-2014 22:16:01

pacopenin,

Cita:

Empezado por pacopenin
...al evaluar un if...la condición devuelve falso y está ejecutando las instrucciones correspondientes al valor verdadero...Lo pongo no para buscar una solución, sino como curiosidad...

Pregunto:

1- ¿Cual es el tipo de dato de la variable Name?.

2- ¿Como solucionas el problema en las condiciones que lo planteas? :confused:

Nelson.

Casimiro Noteví 16-04-2014 22:28:47

Si no me equivoco, esas cosas suelen suceder, se deben a optimizaciones del compilador. Puede ser porque no se haga uso después de ese valor/variable, o alguna otra causa similar.
Creo :)

pacopenin 16-04-2014 23:52:11

Casimiro, me imagino que tiene que ver con lo que comentas, pero recuerdo haber perdido mucho tiempo hace unos años peleándome contra algo similar.

Nelson, la variable name es un string. Ante la perspectiva de volver a perder el tiempo, modifiqué la función que da entrada denominada buscaGrid y que ejecuta un Query en el cual ya hago ese filtrado.

Nunca os pasó algo similar? Será que tengo una lógica extraña y ya he forzado dicha situación varias veces.:confused::rolleyes:

cloayza 17-04-2014 18:53:14

Amigo a mi parecer está bien la evaluación del resultado.

Suponiendo lo siguiente
Código Delphi [-]
    Name:='FFormaPago';

    {Esta expresión debería devolver True si se cumple alguna de las condiciones}
    (Name='FCat') Or (Name='FUsu') or (name='FConcepto') or (Name='FFormaPago');

    {En este caso se cumple que Name='FFormaPago', por lo tanto el resultado de la expresión es True}

     If Not  ((Name='FCat') Or (Name='FUsu') or (name='FConcepto') or (Name='FFormaPago')) then

    {Aquí estas evaluando la negación de True, que es False, por lo tanto se cumple la condición del IF}
    
     {Deberías cambiar la condición por...}
     If ((Name='FCat') Or (Name='FUsu') or (name='FConcepto') or (Name='FFormaPago'))=False then

Saludos cordiales

pacopenin 17-04-2014 22:17:04

Cita:

Empezado por cloayza (Mensaje 475269)

Código Delphi [-]

     If Not  ((Name='FCat') Or (Name='FUsu') or (name='FConcepto') or (Name='FFormaPago')) then

    {Aquí estas evaluando la negación de True, que es False, por lo tanto se cumple la condición del IF}

Gracias por el comentario cloayza, pero no puedo estar de acuerdo con lo que comentas. Ese razonamiento a mi no me encaja, sino
esto no funcionaría así ¿no?



Saludos,

nlsgarcia 18-04-2014 02:29:32

pacopenin,

Cita:

Empezado por pacopenin
...sino esto no funcionaría así ¿no?...

Es correcto :) ^\||/

Nelson

ecfisa 18-04-2014 02:51:36

Hola.

Según las leyes de Augustus De Morgan,

1) La negación de la conjunción es la disyunción de las negaciones. -(A ^ B) = -A v -B
2) La negación de la disyunción es la conjunción de las negaciones. -(A v B) = -A ^ -B

1)
Código Delphi [-]
  if not(A and B) then 
  // es equivalente a:
  if not A or not B then
2)
Código Delphi [-]
  if not (A or B) then 
  // es equivalente a:
  if not A and not B then

Por lo tanto la expresión:
Código Delphi [-]
  if not((Name='FCat')or(Name='FUsu')or(name='FConcepto')or(Name='FFormaPago')) then
  // es equivalente a:
  if not (Name='FCat') and not (Name='FUsu') and not(Name='FConcepto') and not (Name='FFormaPago') then
  // o mas comúnmente:
  if (Name<>'FCat')and(Name<>'FUsu')and(Name<>'FConcepto')and(Name<>'FFormaPago') then

Saludos :)

pacopenin 18-04-2014 11:30:49

Cita:

Empezado por ecfisa (Mensaje 475284)

Código Delphi [-]
  if (Name<>'FCat')and(Name<>'FUsu')and(Name<>'FConcepto')and(Name<>'FFormaPago') then

Recuperando código de SVN se puede ver que probé de varias formas antes de darme por vencido.




Por mi experiencia, como ya comenté, decidí no dar demasiadas vueltas y atacar la solución desde otro punto de vista. La cuestión no es tanto como expresar la condición sino que, a partir de los valores que se ven en la pantalla de depuración, la instrucción if funciona de forma anómala. No se si es un bug o un funcionamiento que se me escapa, pero como ya comenté, en mis casi 20 años de desarrollo con Delphi desde la versión 1.0, me he encontrado otras dos veces con esta anomalía. La anterior vez creo recordar que estaba relacionado con un valor (boolean) devuelto por una función y recuerdo que perdí mucho tiempo tratando de dilucidar porque un valor false hace que se ejecute el código correspondiente a verdadero del if.

Saludos,

ecfisa 18-04-2014 18:57:20

Hola pacopepin.

La condición del código de tu primer mensaje, está correctamente definida y tendría que funcionar del mismo modo para las diferentes formas de expresarlo, eso quería resaltar en el mensaje anterior.

Nunca me ha sucedido antes (o no me enteré :o) y luego de leer tu mensaje traté de forzar el caso con Delphi 7 de varios modos sin lograrlo, lo que era de esperar ya que comentas que sólo te ocurrió tres veces en tanto tiempo.

Creo que la causa mas plausible es la que sugiere Casimiro en el mensaje #3. Tal vez el compilador tratando de optimizar el código, en algunas condiciones, cambie la lógica del predicado.

Saludos :)

mamcx 19-04-2014 02:20:10

O algo mas. El código compilado no es el mismo al código escrito -por ejemplo, un cambio que se le hizo y luego el compilador no refresco ese cambio-. Eso me ha pasado en Delphi, .NET, Obj-C, Python por multiples razones. EL chiste seria ver que muestra el ensamblador.

nlsgarcia 19-04-2014 05:01:52

pacopenin,

Cita:

Empezado por pacopenin
...al evaluar un if...la condición devuelve falso y está ejecutando las instrucciones correspondientes al valor verdadero...Lo pongo no para buscar una solución, sino como curiosidad...

Pregunto:

1- ¿Donde y como se asigna el valor a la variable Name?, ¿Puedes publicar el código de asignación?.

2- ¿Que unidades están declaradas en la unidad que presenta el problema?.

3- Si revisas el valor de la variable Name con Ctrl+F7 (Evaluate/Modify), ¿Que valor tiene?.

Espero sea útil :)

Nelson.

pacopenin 19-04-2014 11:33:40

Desgraciadamente no puedo recuperar la situación del proyecto en el estado en que se produjo ese problema ya que esta última semana he modificado mucho código y volver a ese punto me llevaría bastante tiempo (que ahora mismo no tengo).

Cita:

Empezado por nlsgarcia (Mensaje 475332)

1- ¿Donde y como se asigna el valor a la variable Name?, ¿Puedes publicar el código de asignación?.

Name es la propiedad correspondiente al form. El código corresponde al método show.
Como aclaración comentar que todo funcionaba bien hasta que añadí la cuarta condición. Con tres llevaba años (desde el 2010) funcionando sin problema.

Cita:

Empezado por nlsgarcia (Mensaje 475332)

2- ¿Que unidades están declaradas en la unidad que presenta el problema?.

Código Delphi [-]
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls, Grids, DBGrids, SMDBGrid, JvExExtCtrls,
  JvExtComponent, JvPanel, DBCtrls, DB, ZAbstractRODataset, ZAbstractDataset,
  ZDataset, Menus, JvComponentBase, JvFormPlacement;

....

implementation

uses UDatos, lib01, LibEngine;

Las uses debajo de implementation corresponden a unidades propias del proyecto desarrolladas por mi.

Cita:

Empezado por nlsgarcia (Mensaje 475332)

3- Si revisas el valor de la variable Name con Ctrl+F7 (Evaluate/Modify), ¿Que valor tiene?.

Los valores de las variables y de la evaluación de la expresión puedes verlas en la primera pantalla que puse al lado izdo.

Cita:

Empezado por mamcx (Mensaje 475328)
El código compilado no es el mismo al código escrito -por ejemplo, un cambio que se le hizo y luego el compilador no refresco ese cambio-. ... EL chiste seria ver que muestra el ensamblador.

Estoy de acuerdo.^\||/

Cita:

Empezado por ecfisa (Mensaje 475307)
La condición del código de tu primer mensaje, está correctamente definida y tendría que funcionar del mismo modo para las diferentes formas de expresarlo, eso quería resaltar en el mensaje anterior.

Creo que la causa mas plausible es la que sugiere Casimiro en el mensaje #3. Tal vez el compilador tratando de optimizar el código, en algunas condiciones, cambie la lógica del predicado.
Saludos :)

Y contigo, ^\||/

Saludos,

nlsgarcia 19-04-2014 17:51:51

pacopenin,

Cita:

Empezado por pacopenin
...Los valores de las variables y de la evaluación de la expresión puedes verlas en la primera pantalla que puse al lado izdo...

No necesariamente el valor mostrado en la pantalla de Watch List sera igual al valor visto con Ctrl+F7 (Evaluate/Modify).

Una vez me paso algo similar con una variable tipo Double en Delphi 7 y había diferencias en ambas visualizaciones, esto era lo que causaba la confusión al momento de hacer el Debug dado que en mi caso la condición no se cumplía a pesar de que en la pantalla de
Watch List se mostraba el valor supuestamente correcto, pero con Ctrl+F7 (Evaluate/Modify) se mostraba el valor que realmente se estaba evaluado en la condición IF.

Creo que es más factible que sea algún error aleatorio muy esporádico y de condiciones muy particulares en la visualización de las variables en el
Watch List o cuando se coloca el Mouse sobre una variable para ver su valor, que un error del compilador ya sea por optimización o cualquier otro tipo.

En el Msg #1 comentastes que el error se presento en la versiones de Delphi 2, Delphi 6 y Delphi 2007, es muy improbable que un error del compilador de ese tipo haya sobrevivido tantos años y a tantos proyectos en todo el mundo.

Pregunto: ¿Ha alguien en el Club Delphi le ha pasado en alguna versión de Delphi algo similar a lo comentado en este hilo? :confused:

Espero sea útil :)

Nelson.

Al González 19-04-2014 23:29:23

Cita:

Empezado por nlsgarcia (Mensaje 475336)
Pregunto: ¿Ha alguien en el Club Delphi le ha pasado en alguna versión de Delphi algo similar a lo comentado en este hilo? :confused:

A mí, y estoy seguro que a muchos otros compañeros también les ha ocurrido. :) ^\||/

Creo que la gran mayoría de los programadores que venimos de Turbo Pascal o de Visual Basic (perdón que haga mención a algo tan bueno junto con algo tan malo), hemos aprendido aquella popular lección de por qué la sentencia With de Delphi debe ser empleada bajo cautela.

pacopenin: Supongo que "Datos" es un módulo de datos o algún otro objeto que, como sucede en el caso de los formularios, también posee una propiedad llamada Name (todas las clases derivadas de TComponent la heredan de ésta). Y hay que decir que el depurador es muy bueno para determinar el ámbito de un identificador añadido a la lista de observaciones, excepto cuando se trata de algún miembro sin calificar perteneciente a un objeto indicado en With...Do.

En términos llanos, el depurador está evaluando la propiedad Name del formulario, pero el If está evaluando la propiedad Name del objeto, registro o interfaz Datos.

Desde luego solo tú, que tienes el código, podría confirmar si mi teoría es cierta.

Un cordial saludo.

Al González.

nlsgarcia 20-04-2014 02:27:28

pacopenin,

Cita:

Empezado por Al González
...el depurador es muy bueno para determinar el ámbito de un identificador añadido a la lista de observaciones, excepto cuando se trata de algún miembro sin calificar perteneciente a un objeto indicado en With...Do...

:) ^\||/

Revisa esta imagen:



La imagen anterior muestra exactamente el caso planteado en el Msg #15 y el mismo comportamiento del IF en el Msg #1, esto es mucho más probable que un error del compilador ya sea por optimización o cualquier otro tipo.

Espero sea útil :)

Nelson.

pacopenin 20-04-2014 12:55:03

Guau. Estoy sin palabras. A pesar de que desde el principio comenté que no era un reto, estoy más que sorprendido por lo acertado y oportuno de vuestras deducciones. Obviamente habéis sabido entender la naturaleza de problema y buscar la solución. Yo me había quedado en lo evidente, lo visual y lo lógico. Gracias por el tiempo dedicado, la explicación y como no, la consiguiente reproducción del problema. Una vez más repito que estoy sin palabras. Gracias.

v:-)vv:-)v||-||#:-)#^\||/^\||/

Casimiro Noteví 20-04-2014 13:52:45

Cita:

Empezado por pacopenin (Mensaje 475342)
Guau. Estoy sin palabras. A pesar de que desde el principio comenté que no era un reto, estoy más que sorprendido por lo acertado y oportuno de vuestras deducciones. Obviamente habéis sabido entender la naturaleza de problema y buscar la solución. Yo me había quedado en lo evidente, lo visual y lo lógico. Gracias por el tiempo dedicado, la explicación y como no, la consiguiente reproducción del problema. Una vez más repito que estoy sin palabras. Gracias.

++1 para los que han participado (menos yo, claro)

Al González 21-04-2014 02:22:54

Cita:

Empezado por Casimiro Notevi (Mensaje 475343)
++1 para los que han participado (menos yo, claro)

+1 para todos los que podemos darnos el "lujo" de ayudar de cuando en cuando a los colegas de profesión, y +++1 para los que siempre están ahí apoyando igual o más. :)

Como es deseable, esta solución se construyó de forma cooperativa, y eso nos permite recordar quiénes somos. (Hay un par de pequeñas erratas pendientes de enmendar). ;)

Saludos.


La franja horaria es GMT +2. Ahora son las 07:18:38.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi