2009-09-28 12 views
10

Recientemente migré mi proyecto Qt de Linux a Vista, y ahora estoy depurando señales a ciegas.Aplicación Qt GUI: ¿advertencia si falló QObject :: connect()?

En Linux, si QObject :: connect() falla en una compilación de depuración, aparece un mensaje de advertencia en stderr. En Windows, no hay salida de consola para aplicaciones GUI, solo una llamada OutputDebugString.

Ya instalé DebugView, y atrapa mi propia salida qDebug() muy bien, pero todavía no hay advertencia en las señales fallidas.

Una posible solución sería usar el autocompletado de QtCreator para las señales, pero me gusta Eclipse, y el uso de ambos es un PITA. ¿Alguna idea sobre cómo obtener información de señal/ranura en tiempo de ejecución?

Editar: Me acabo de dar cuenta de que connect() devuelve bool, lo que resuelve el problema inmediato, por feo que sea. Sin embargo, esto no resuelve los casos donde QMetaObject::connectSlotsByName() falla, y este se ejecuta automáticamente con widgets.

Respuesta

10

Llamar a la función estática QErrorMessage :: qtHandler().

Según la documentación, esto 'instala un manejador de mensajes usando qInstallMsgHandler() y crea un QErrorMessage que muestra los mensajes qDebug(), qAdvertencia() y qFatal()'.

Como alternativa, instale un controlador de mensajes con qInstallMsgHandler().

Otra alternativa (que se describe en un post-interés qt) es algo como esto:

#ifdef _DEBUG 
#define connect(connectStmt) Q_ASSERT(connect(connectStmt)) 
#endif 

... y por lo que vale la pena, aquí hay algunas señales y ranuras de depuración sugerencias compilé: http://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/

+1

¡Esto es realmente útil! – Pepe

1

Si usa Visual Studio, puede agregar una consola a cualquier aplicación de QT.
Vaya a las propiedades del proyecto, en Enlazador-> Configuración cambie el "Sub-sistema" para decir "Consola"

Ahora recompile su código y la consola aparecerá cuando active la aplicación. Si desea deshacerse de él, simplemente cambie el SubSystem de nuevo a "Windows"

No estoy seguro de si esto es posible con QtCreator.

Otra opción es utilizar llamadas win32 nativas como AttachConsole() para crear manualmente la consola y adjuntarla a stdout y stderr. ver here para más detalles sobre esto.

0

puede redirigir stdout/stderr con bastante facilidad: hacer una clase que deriva de std :: basic_streambuf y sobrecargas xsputn() y desbordamiento(), a continuación, utilizar por ejemplo std :: cerr.rdbuf (instanceOfYourRedirectClass) para redirigir todo el ouptut stderr a una función de devolución de llamada que proporcione.

Aquí hay una versión simplificada de lo que uso; en función de sus necesidades puede que tenga que agregar lógica adicional para jugar con el manejo de los caracteres de fin de línea, etc.

template< class Elem = char, class Tr = std::char_traits<Elem> > 
class Redirector : public std::basic_streambuf<Elem, Tr> 
{ 
    typedef void (*pfncb) (const Elem*, std::streamsize); 

public: 
    Redirector(std::ostream& a_Stream, pfncb a_Cb) : 
    m_Stream(a_Stream), 
    m_pCbFunc(a_Cb), 
    { 
     //redirect stream 
    m_pBuf = m_Stream.rdbuf(this); 
    }; 

    ~Redirector() 
    { 
     //restore stream 
    m_Stream.rdbuf(m_pBuf); 
    } 

    std::streamsize xsputn(const Elem* _Ptr, std::streamsize _Count) 
    { 
    m_pCbFunc(_Ptr, _Count); 
    return _Count; 
    } 

    typename Tr::int_type overflow(typename Tr::int_type v) 
    { 
    Elem ch = Tr::to_char_type(v); 
    m_pCbFunc(&ch, 1); 
    return Tr::not_eof(v); 
    } 

protected: 
    std::basic_ostream<Elem, Tr>& m_Stream; 
    std::streambuf*    m_pBuf; 
    pfncb       m_pCbFunc; 
}; 

Uso:

void outcallback(const char *ptr, std::streamsize count) 
    { 
    if(*ptr != gc_cEOL) //ignore eof 
     OutputDebugString(ptr); 
    } 

    Redirector<> redirect(std::cout, mycallback); 
+0

Redirige stdout con printf() también, o simplemente std :: cout? Sospecho que esto último, lo que lo hace menos útil en este caso. – Macke

2

Mi enfoque es volver a enlazar el motor de registro con Qt qInstallMsgHandler y hago mi propio registro para archivar y consolar.

De esta manera, sé que todos los mensajes de error/advertencia se graban y puedo analizarlos incluso después de que el programa haya dejado de ejecutarse.

P.S: QtCreator intercepta esos mensajes y los muestra en el panel de salida de la aplicación.

+0

Gracias, esto sin duda ayuda, aunque estoy empezando a creer que la DLL Qt es simplemente silenciosa. Ya puedo ver la salida de qDebug(), así que en teoría, debería haber aparecido en DebugView también. –

1

Puede usar el ID de Qt oficial: QtCreator. Contiene una consola de salida donde verá cualquier problema con las señales. El error de señal se genera en la depuración Y en la ejecución de la versión.

4

La solución que me gusta de esto es para establecer

QT_FATAL_WARNINGS=1 

en el entorno del programa cuando se depura. Eso hace que el programa falle, brindándote un agradable seguimiento, especialmente si ejecutas el código en un depurador. Si no desea el bloqueo, consulte la respuesta anterior.

+0

No hay rastro, lamentablemente, con MinGW: solo "Una aplicación tiene ... de una manera inusual" (Posiblemente esto funciona mejor con MSVC). – mlvljr

+0

Prefiero esto como la solución (en VS 2012 se muestra la pila de llamadas) ya que la redefinición de CONNECT no funcionó, especialmente si el problema de vinculación está en una DLL diferente – Samuel

0

La mayoría de las veces solo quiero llamar la atención de vez en cuando: Solo ponga un punto de interrupción en línea "int dummyPutBreakpointHere = 23;"

in main.C: 

static QtMessageHandler defaultMessageHandler; 
void myRazorsharpMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) 
{ 
    if (type > QtDebugMsg) { 
     int dummyPutBreakpointHere= 23; 
    } 
    defaultMessageHandler(type, context, msg); 
} 
... 
later in main(): defaultMessageHandler= qInstallMessageHandler(0); 
Cuestiones relacionadas