Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Problemas con creación de hilo

Hola amigos, tengo esto en un botón del form:
Código PHP:
Depurador->InitDebug(NULL,MODE_ATACH_BY_WINDOW_NAME,wndName,NULL); //Inicializamos el debugger
Depurador->LoopDebug(); //Arrancamos el bucle de depuracion
//::Sleep(20);
Depurador->SetBP(DIR_BP_IDS); 
El metodo LoopDebug crea el hilo:
Código PHP:
void TDebugger::LoopDebug(void)
{
    
//Creo el hilo suspendido
    
HiloDepuracion = new(std::nothrowTHiloDebugger(false,Mode,PathFile,NameWindow,pid,this); 
El problema que tengo es que tarda menos en ejecutarse la siguiente linea del botón que internamente hace esto:
Código PHP:
bool THiloDebugger::SetBP(DWORD address)
{
        
bool salida true;
        
BYTE bp 0xCC;
        
unsigned long retval 0;
        
BYTE original;
        
TBP MyBP;
        
int pos;

        
pos SearchBPOnList(address, &MyBP); 
que en crearse el hilo y ejecutar cosas como estas:
Código PHP:
void __fastcall THiloDebugger::Execute()
{
        
DEBUG_EVENT DebugEv;
        
HANDLE CurrentExceptionThread;
        
DWORD dwContinueStatus;
        
int Error;
        
TDll *ItemDLL;
        
bool salir=false;

        
ListaBPs = new TList;
        
ListaDlls = new TList;
        
ListaThreads = new TList;

        
Synchronize(OnInitLoopDebugThread); //Usaremos este evento para inicialización de variables en la clase usuario si se requiere. 
y cuando intento poner el Breakpoint hace esto internamente:
Código PHP:
int THiloDebugger::SearchBPOnList(DWORD addresspBP lpMyBP)
{
        
pBP BP;
        
int x 0;
        
bool encontrado false;
        for(
x=0ListaBPs->Countx++)
        {
                
BP = (TBP*)ListaBPs->Items[x];
                if(
BP->dir == address)
                { 
Con lo que me encuentro con que al poner el Breakpoint lo va a buscar en la TList ListaBPs y esta aun no se ha creado. Lo he solucionado poniendo un ::Sleep(20) justo antes de poner el Breakpoint pero creo que es una autentica chapuza. ¿que podría hacer para no tener este problema?
Intenté poniendo después de crear el hilo con:
Código PHP:
HiloDepuracion->WaitFor(); 
pero me cansé de esperar y no regresa nunca porque supongo que eso espera hasta que termine el hilo y el hilo es el que tiene el bucle de los eventos así que no va a salir nunca.
Responder Con Cita
  #2  
Antiguo 08-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
No está nada claro cómo y cuando has creado el hilo, es decir, si el hilo es un TThread, puedes crearlo en suspensión o en ejecución directa. El Método Execute debe contener un bucle principal que se ejecutará durante toda la vida del thread, normalmente se coloca un semáforo (Terminated) para terminarlo. Una forna de detectar cuando el hilop se esta ejecutando, llamando hilo al código del bucle principal, es colocar una variable de control que puede ser Terminated u otra que diseñes. Esa variable puede ser booleana y actuar como semáforo que se activa cuando te interese y otras partes de la clase pueden consultar para actuar en consecuencia.

Saludos.
Responder Con Cita
  #3  
Antiguo 08-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Mira creo que Windows 10 gestiona los hilos de manera distinta porque si lo ejecuto en XP va bien pero si lo ejecuto en Windows 10 no va bien y ademas de repente me ha dejado de funcionar CreateProcess, OpenProcess, y fopen que los uso para abrir el archivo para depurarlo, atachearlo, y mirar su md5 respectivamente.
Ademas me he dado cuenta de que al atachear al proceso en xp tengo el control del mismo entrando el el bucle del hilo pero de los breakponts nada de nada.
Ademas ahora el antivirus que trae Windows 10 me lo reconoce como un virus "Trojan:Script/Conteban.A!ml" y de troyano no tiene nada jajaja. De locos vamos.
Os pongo el proyecto con una pequeña aplicación que lo unico que hace es mostrar un MessageBox al darle al botón y la idea es poner un Breakpoint en MessageBoxA y cuando pare mostrar yo un mensaje pero no para

https://mega.nz/file/Ukt0hSjZ#IKeNQt...6_XxZOLnthbibc
El hilo no lo creo suspendido pero se ve que tendrá menos prisa que el resto en Windows 10 porque tengo que andar poniendo pausas por doquier y ni así se espabila.
Responder Con Cita
  #4  
Antiguo 09-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
No he visto ese código pero me inclino a pensar que estás usando variables compartidas entre threads lo que los convierte en inestables. LAs APIs CreateProcess, OpenProcess, y fopen son thread safe pero eso no implica que si compartes variables, provoquen el fallo. En el caso de abrir ficheros en modo no compartido está claro que distintos threads no los podarán tener abiertos al mismo tiempo. Si compartes los Handles, un thread pisa a otro. La comunicación d¡con a VCL no es ThreadSafe con lo que debes usar Synchronize. Tienes que ser muy cuidadoso y usar semáforos para sincronizarlo todo bien.


Saludos.
Responder Con Cita
  #5  
Antiguo 11-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
A ver si me puedes ayudar, el caso es que solo hay dos hilos, el principal y el del debuger. El principal crea al hilo del debuger y posteriormente llama a métodos del hilo del debuger los cuales necesitan acceder a unas estructuras y variables que se crean al inicio del execute del hilo con lo que se da a veces el caso de que el hilo principal va más rápido que el secundario y accede a las variables sin haberse creado antes en el hilo secundario. He estado buscando la manera de solucionar eso y no me sirve waitfor porque espera a que acabe el hilo y en este caso el secundario contiene el bucle de eventos del debuger con lo que no acabará. La solución que encontré es usar TEvent y usarlo en la zona de código que quiero que se ejecute en el hilo secundario para que asigne la memoria a las variables y que una vez hecho eso ya continúe el hilo principal pero solo he encontrado esto en español: https://elvex.ugr.es/decsai/builder/...rdination.html
Y no tengo nada claro como hacerlo.
Responder Con Cita
  #6  
Antiguo 11-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Pero quizás tengas que preguntarte primero si en realidad te hacen falta dos hilos.


En caso afirmativo, una solución rápida es que las variables se creen en la clase TDebugger y se asignen en execute. Las variables que necesita leer el hilo principal siempre deben leerse con un método de TDebuger y a ser posible no deben ser asignadas mientras TDebugger se ejecuta. Puedes saber si la variable leída es válida dándole determinado valor en caso de no ser válido. Por ejemplo, puede ser un puntero inicializado a NULL en cuyo caso no trataras de leerlo, pero puedes hacer un bucle (con un sleep corto) hasta tener un valor correcto. También puedes controlarlas con otra variable que se pone a true cuando el valor es válido...

WaitForSingleObject puede ser usado con otros tipos de Handle que no tienen que ser el Thread, puedes usar un Mutex o un Event. Estos también te pueden servir para poner el hilo a la espera. Todo depende de tu diseño particular.


Saludos.
Responder Con Cita
  #7  
Antiguo 11-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
creo que TEvent es lo mejor pero no se como se usa. Tengo esto.
En el archivo TDebuger.h:
Código PHP:
TEvent *EventoVariablesArmadas
En el TDebuger.cpp:
Código PHP:
bool TDebugger::InitDebug(AnsiString Pathint modeAnsiString WNameDWORD PID)
{
        ...
        ... 
    
EventoVariablesArmadas = new TEvent(false);
    return 
retval;

Código PHP:
void TDebugger::LoopDebug(void)
{
        
HiloDepuracion = new(std::nothrowTHiloDebugger(false,Mode,PathFile,NameWindow,pid,this); // no me gusta no hay control de PathFile en este método.
        
EventoVariablesArmadas->WaitFor(INFINITE);
        if(
HiloDepuracion == NULL)
        {
        ...
                ...

En el THiloDebuger.cpp:
Código PHP:
void __fastcall THiloDebugger::Execute()
{
    
DEBUG_EVENT DebugEv;
        
HANDLE CurrentExceptionThread;
        
DWORD dwContinueStatus;
        
int Error;
        
TDll *ItemDLL;
        
bool salir=false;

        
ListaBPs = new TList;
        
ListaDlls = new TList;
        
ListaThreads = new TList;

        
//Synchronize(OnInitLoopDebugThread); //Usaremos este evento para inizialización de variables en la clase usuario si se requiere.

        
si.cb sizeof(STARTUPINFO);
        
GetStartupInfo(&si);

        
// El proceso se tiene que crear en la misma función donde está el hilo del depurador sino no vale
        
switch(Mode){
                case 
MODE_NORMAL:
                        
CreateProcess(PathFile.c_str(),NULLNULLNULLFALSEDEBUG_PROCESS DEBUG_ONLY_THIS_PROCESSNULLNULL, &si, &pi);
                        break;
                case 
MODE_ATACH_BY_WINDOW_NAME:
                        if(!
AtachProcessByNameWindow(WindowName.c_str(),Error)){
                                return;
                        }else{
                                
//Aqui Obtengo informacion del proceso
                                
EnumerarModulospi.dwProcessId );
                                
SystemEntryPoint=0;
                        }
                        break;
                case 
MODE_ATACH_BY_PID:
                        if(!
AtachProcessById(pid,Error)){
                                return;
                        }else{
                                
//Aqui Obtengo informacion del proceso
                                
EnumerarModulospi.dwProcessId );
                                
SystemEntryPoint=0;
                        }
                        break;
                default:
                        return;
        }

        
InfoProcess.hProcess pi.hProcess;
        
InfoProcess.ProcessID pi.dwProcessId;

        
EventoVariablesArmadas->SetEvent();
               ...
               ...
        if(
EventoVariablesArmadas != NULL)
            
delete EventoVariablesArmadas;

No se porque al llamar al constructor del TEvento me da NULL pero si en vez de declararlo en TDebugger.h lo hag en TDebugger.cpp ahi si me asigna bien pero claro, no puedo acceder desde THiloDebugger.
Responder Con Cita
  #8  
Antiguo 11-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
SetEvent lo señaliza de forma que WaitForSingleObject(hEvent, INFINITE) deja de esperar. por ejemplo.
Si usas TEvent, WaitFor haría lo mismo.


Es una forma de hacer esperar hasta que algo señaliza el evento.


Saludos.
Responder Con Cita
  #9  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Si, eso ya lo vi pero el caso es que al ejecutar el constructor me da NULL si lo declaró en TDebugger.h y me da un valor diferente de NULL si lo hago en TDebugger.cpp. No entiendo porque pasa eso sí Tdebugger.h se incluye en TDebugger.cpp.
Responder Con Cita
  #10  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Me he dado cuenta que si la declaro como:
Código PHP:
static TEvent *EventoVariablesArmadas
en el archivo de cabecera ya si me crea el TEvent o eso parece porque no retorna NULL en el constructor pero al intentar operar desde el hilo sobre él alli si vale NULL. No entiendo que está pasando
Responder Con Cita
  #11  
Antiguo 12-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Es buena idea declararla static de la clase pero entonces no la inicializa el constructor de la misma. Deber incluir en la parte de código esa inicialización. Lee sobre los miembros estáticos de un a clase en CPP. Son miembros que no pertenecen al objeto, sino a la clase misma por lo que existen siempre aún sin instanciar ningún objeto. Se puede acceder a ellos a través del nombre de la clase o desde un objeto.

En debugger.h
Código PHP:
TEdbugger::class...
.....
public:
static 
TEvent  *Event;
..... 
En Debugger.cpp

Código PHP:
TEdbugger::TEdbugger.....
....
Funciones.....

//Fuera de cualquier función:
TEvent*  TDebugger::Event = new TEvent(false);

...... 
Ten en cuenta que al ser un miembro de la clase, será el mismo para todos los objetos Debugger, estará compartido y accesible por todos (no está encapsulado).

Saludos.
Responder Con Cita
  #12  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Pero para acceder a el desde THiloDebugger ¿podría sin haber creado una instancia de la clase TDebuger? Lo digo porque en ese momento aún no existe.
Responder Con Cita
  #13  
Antiguo 12-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por aguml Ver Mensaje
Pero para acceder a el desde THiloDebugger ¿podría sin haber creado una instancia de la clase TDebuger? Lo digo porque en ese momento aún no existe.
No leíste bien todo mi mensaje:
Cita:
Empezado por escafandra Ver Mensaje
Lee sobre los miembros estáticos de un a clase en CPP. Son miembros que no pertenecen al objeto, sino a la clase misma por lo que existen siempre aún sin instanciar ningún objeto. Se puede acceder a ellos a través del nombre de la clase o desde un objeto.
Saludos.
Responder Con Cita
  #14  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Ok gracias, lo intentaré y comento.
Gracias.
Responder Con Cita
  #15  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Tengo una duda. Supongamos que ya tengo puesto el código que me indicas en TDebugger.h y en TDebugger.cpp y quiero llamar a un método del TEvent ¿Tengo que volver a poner esto en THilodebugger?
Código PHP:
TEvent*  TDebugger::Event = new TEvent(false); 
¿O directamente hago esto?
Código PHP:
TDebugger::Event->SetEvent(); 
Responder Con Cita
  #16  
Antiguo 12-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
No puedes volver a crear el miembro Event, simplemente usarlo como pones en la segunda opción. Recuerda que puedes acceder a él a traves de la clase o de cualquier objeto instanciado de esa clase, pero siempre será un miembro cuyo valor es el mismo para todos los objetos de esa clase. Es un miembro e la clase misma y no de un objeto particular.


Saludos.
Responder Con Cita
  #17  
Antiguo 12-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
A ver, pensándolo bien, si lo pongo así se podría acceder a el desde el TForm1 de la misma manera y no me interesa que sea "visible" para TForm1 así que ¿Podría colocarlo en la clase THiloDebugger? Lo digo porque de esa manera no sería accesible para TForm1 ¿Sería posible hacer eso o no se podría?
O sea:
En THiloDebugger.h:
Código PHP:
THiloDebugger::class...
.....
public:
static 
TEvent  *Event;
..... 
En THiloDebugger.cpp
Código PHP:
//Fuera de cualquier función:
TEvent*  THiloDebugger::Event = new TEvent(false); 
En la función:
Código PHP:
THiloDebugger::Event->SetEvent(); 
y en TDebugger.cpp:
Código PHP:
THiloDebugger::Event->WaitFor();
o:
WaitForSingleObject((HANDLE)THiloDebugger::Event->Handle,INFINITE); 

Última edición por aguml fecha: 12-05-2020 a las 23:39:31. Razón: Aclaracion
Responder Con Cita
  #18  
Antiguo 13-05-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Un miembro publico es visible siempre, lo pongas donde lo pongas. Para hacerlo invisible a todos menos a una clase, tienes que hacerlo privado y usar el recurso de las clases amigas.


Saludos.
Responder Con Cita
  #19  
Antiguo 13-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Muchas gracias, ha funcionado genial .
Responder Con Cita
  #20  
Antiguo 13-05-2020
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Ahora tengo una duda, esta linea en Embarcadero C++builder 2010 puede ser de dos maneras:
Código PHP:
TEvent*  THiloDebugger::EventHiloArmado = new TEvent(NULL,false,false,"",false);
TEvent*  THiloDebugger::EventHiloArmado = new TEvent(false); 
pero en Borland C++Builder 6 tiene que ser si o si asi:
Código PHP:
TEvent*  THiloDebugger::EventHiloArmado = new TEvent(NULL,false,false,""); 
¿Sabéis el modo de que el compilador pueda elegir cual de ellas usar?
Lo pregunto porque no veo que haya en las environment path ninguna variable que indique la versión y no se que hacer a parte de tener un proyecto para cada una de las versiones.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Problemas para acceder a componenente de un Form desde un Hilo NEG1414 C++ Builder 3 05-02-2015 11:19:10
Problemas con ejecución de hilo GerTorresM OOP 3 23-10-2014 19:01:12
Problemas con un Hilo aguml C++ Builder 10 08-03-2014 00:20:58
cuando llamo ejecutar un hilo dentro del proceso del hilo no lo hace robertosc Varios 1 14-08-2007 22:11:09


La franja horaria es GMT +2. Ahora son las 10:39:07.


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