Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Problemas con un condicional (https://www.clubdelphi.com/foros/showthread.php?t=85586)

aguml 03-04-2014 20:12:49

Problemas con un condicional
 
Hola amigos, pues mi problema es que no consigo hacer que este condicional haga lo que yo quiero:

Código:

if((DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] == 0 && Dbg->MemoryBP.Type == ON_ACCESS) ||
  (DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] == 0 && Dbg->MemoryBP.Type == ON_EXECUTION) ||
  (DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] == 1 && Dbg->MemoryBP.Type == ON_WRITE))
{
        Synchronize(OnMemoryBPEventThread);
}

Lo explico un poco:
La variable DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] da 0 si la excepcion es por ejecucion o por lectura y da 1 si es por escritura.
ON_ACCESS, ON_EXECUTION y ON_WRITE son tres constantes que defino asi:

#define ON_ACCESS PAGE_NOACCESS
#define ON_WRITE PAGE_EXECUTE_READ | PAGE_GUARD
#define ON_EXECUTION PAGE_READWRITE | PAGE_GUARD

La idea es que solo entre en uno de estos 3 casos:
1ª linea -> si ExceptionInformation[0] == 0 y el tipo es ON_ACCESS
2ª linea -> si ExceptionInformation[0] == 0 y el tipo es ON_EXECUTION
3ª linea -> si ExceptionInformation[0] == 1 y el tipo es ON_WRITE

El problema es que entra siempre aunque no se cumplan ninguna de las 3 condiciones, o sea, si el tipo es ON_WRITE y ExceptionInformation[0] == 0 entra y no debería. ¿que hago mal en el condicional? Estoy loco dandole vueltas y no veo el fallo.
Gracias de antemano.

ecfisa 04-04-2014 02:49:03

Cita:

Empezado por aguml (Mensaje 474772)
...
La idea es que solo entre en uno de estos 3 casos:
1ª linea -> si ExceptionInformation[0] == 0 y el tipo es ON_ACCESS
2ª linea -> si ExceptionInformation[0] == 0 y el tipo es ON_EXECUTION
3ª linea -> si ExceptionInformation[0] == 1 y el tipo es ON_WRITE

Hola aguml.

Según lo que comentas arriba tendría que ser:
Código:

...
  if(((DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] == 0) &&
    (Dbg->MemoryBP.Type == ON_ACCESS || Dbg->MemoryBP.Type == ON_EXECUTION)) ||
    (DebugEv.u.Exception.ExceptionRecord.ExceptionInformation[0] == 1 &&
      Dbg->MemoryBP.Type == ON_WRITE))
    ShowMessage("Cumple la condición");
  else
    ShowMessage("No cumple la condición");
...


aguml 04-04-2014 15:17:13

Vale, el problema no era ese porque mi condicional, aunque algo menos eficiente, tambien era válido. Al final ha quedado así:

Código:

if((ExceptionAccess.LastExceptionTypeOnMBP == 0 && (Dbg->MemoryBP.Type == int(ON_ACCESS) ||
  (Dbg->MemoryBP.Type == int(ON_EXECUTION) &&
  (ExceptionAccess.LastExceptionAddressOnMBP >= ExceptionAccess.LastExceptionAccessAddressOnMBP) &&
  (ExceptionAccess.LastExceptionAddressOnMBP <= ExceptionAccess.LastExceptionAccessAddressOnMBP)))) ||
  (ExceptionAccess.LastExceptionTypeOnMBP == 1 && Dbg->MemoryBP.Type == int(ON_WRITE)))
{
          OnMemoryBPEventThread();
}

El problema estaba en que las constantes que defino, por alguna razón, no funcionan bien sin el cast ese que le pongo. ¿No hay manera de crear esas constantes usando #define y que se creen como enteros para no tener que hacerles cast?

ecfisa 04-04-2014 18:57:55

Cita:

Empezado por aguml (Mensaje 474796)
¿No hay manera de crear esas constantes usando #define y que se creen como enteros para no tener que hacerles cast?

Hola aguml.

No estoy seguro de entenderte... ¿ Te referis a algo así ?
Código:

#define ON_ACCESS      1 // (PAGE_NOACCESS)
#define ON_WRITE    288 // (PAGE_EXECUTE_READ | PAGE_GUARD)
#define ON_EXECUTION 260 // (PAGE_READWRITE | PAGE_GUARD)


Saludos :)

aguml 05-04-2014 21:08:30

¿hay diferencia entre hacerlo de una manera o de otra a la hora de la comparación?
Me refiero a hacerlo asi:

Código:

#define ON_WRITE    288 // (PAGE_EXECUTE_READ | PAGE_GUARD)
o asi:

Código:

#define ON_WRITE PAGE_EXECUTE_READ | PAGE_GUARD
¿funciona de manera diferente a la hora de la comparación? El caso es que en el depurador, al parar en el condicional, podia ver como ON_WRITE tenia el valor correcto que debia tener pero no procesaba bien el valor. ¿en tu caso si lo haria? ¿acaso es un problema del #define que no trabaja bien como yo lo hice?

ecfisa 05-04-2014 23:06:41

Hola aguml.
Cita:

Empezado por aguml (Mensaje 474839)
¿hay diferencia entre hacerlo de una manera o de otra a la hora de la comparación?

Depende como hayas declarado la macro.

De este modo:
Código:

#define ON_WRITE PAGE_EXECUTE_READ | PAGE_GUARD
podría arrojar resultados no deseados debido a la precedencia de operadores. Declarada de ese modo, al expandirse en una evaluación tenemos que:
Código:

  if (Valor == ON_WRITE)
es equivalente a escribir:
Código:

if ( (Valor == PAGE_EXECUTE_READ) | PAGE_GUARD)
ya que el operador "==" tiene mayor precedencia que el operador "|". Y definitivamente no es lo que buscas...

La declaración que corresponde a tu propósito es:
Código:

#define ON_WRITE ( PAGE_EXECUTE_READ | PAGE_GUARD )
que al expandirse queda:
Código:

if (Valor == ( PAGE_EXECUTE_READ | PAGE_GUARD ) )
Comprobación:
Código:

#define ON_WRITE1  288
#define ON_WRITE2 (PAGE_EXECUTE_READ | PAGE_GUARD)

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if ( ON_WRITE1 == ON_WRITE2)
    ShowMessage("ON_WRITE1 es igual a ON_WRITE2");
  else
    ShowMessage("ON_WRITE1 es distinto a ON_WRITE2");
}

Saludos :)

aguml 06-04-2014 00:02:22

pues no sabia que podia usarse parentesis en un #define y no habia pensado que pudiera ser problema de precedencia de operadores. Mañana hago la prueba y cambio el codigo. Muchisimas gracias por las aclaraciones, sois un foro cojonudo.


La franja horaria es GMT +2. Ahora son las 05:16:47.

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