Application.exe has triggered a breakpoint Visual Studio 2015 C++



  • @ Danke

    was ich erst mal sicher bin, dass das Problem genau in diese

    class VisaAgilent
    

    ist.

    Das zu finden ist .....



  • deswegen die genannten Tools - die Linux-Varianten sind unschlagbar, der Intel Inspector wohl am einfachsten ausprobierbar - Install und im VStudio einen Knopf drücken



  • Stelle sicher, dass der Thread sich selbst beendet und du ihn nicht dazu zwingst. Auch sind diese Ganzen Konstrukte um new/delete, lock/unlock, strcmp, typedef enum/struct, NULL etc. nicht zu empfehlen oder veraltet, benutz' doch std::string, std::unique_ptr, std::async, std::lock_guard etc. Damit schließt du schonmal unbeabsichtigte Fehler aus.



  • m_MtxProcess.lock();
    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    m_MtxProcess.unlock();
    

    Auf was wartest du denn hier? Ich gehe mal davon aus, dass m_WaitCondProcess vom Typ QWaitCondition ist.

    Wo rufst du das dazu gehörende wakeOne() oder wakeAll() auf?
    Den zweiten Parameter kannst du dir da sparen. Die Doku sagt, dass es sich um ein unsigned long handelt. -1 dürfte dann ULONG_MAX sein, was laut Doku nie in einem Timeout landet und default verhalten ist...



  • Schlangenmensch schrieb:

    m_MtxProcess.lock();
    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    m_MtxProcess.unlock();
    

    Auf was wartest du denn hier? Ich gehe mal davon aus, dass m_WaitCondProcess vom Typ QWaitCondition ist.

    Ich warte bis der thread "run" fertig ist
    ja ist sie auch.

    Schlangenmensch schrieb:

    Wo rufst du das dazu gehörende wakeOne() oder wakeAll() auf?
    Sorry das habe ich vergessen miteinzufügen:

    void VisaAgilent::run()
    {
        bool boRun_l = true;
        bool boSent_l = false;
    
        const char *pStrCmd_l = NULL;
        const char *pStrRsp_l = NULL;
    
        m_enRetVal = enRspError;
    
        if (strcmp(m_ByteArrayWrite.data(),"CreateObject")==0)
        {
            if (this->m_boSimulate == true)
            {
                m_enRetVal = enRspOK;
            }
            else
            {
                m_pTcpSctCtrl = (QTcpSocket *)new QTcpSocket;
                if (m_pTcpSctCtrl != NULL)
                {
                    m_enRetVal = enRspOK;
                }
            }
    
            boRun_l = false;
        }
    
        if (strcmp(m_ByteArrayWrite.data(),"DeleteObject")==0)
        {
            if (this->m_boSimulate == true)
            {
            }
            else
            {
                if (m_pTcpSctCtrl != NULL)
                {
                    delete m_pTcpSctCtrl;
                }
            }
    
            m_enRetVal = enRspOK;
            boRun_l = false;
        }
    
        if (strcmp(m_ByteArrayWrite.data(),"OpenConnection")==0)
        {
            if (this->m_boSimulate == true)
            {
                m_enRetVal = enRspOK;
            }
            else
            {
                m_pTcpSctCtrl->connectToHost(m_strCtrlIP,5025);
                if (m_pTcpSctCtrl->waitForConnected(m_iTimeout) == true)
                {
                    m_enRetVal = enRspOK;
                }
            }
    
            boRun_l = false;
        }
    
        if (strcmp(m_ByteArrayWrite.data(),"CloseConnection")==0)
        {
            if (this->m_boSimulate == true)
            {
                m_enRetVal = enRspOK;
            }
            else
            {
                m_pTcpSctCtrl->disconnectFromHost();
                if ((m_pTcpSctCtrl->state() == QAbstractSocket::UnconnectedState) || (m_pTcpSctCtrl->waitForDisconnected(m_iTimeout)))
                {
                    m_enRetVal = enRspOK;
                }
            }
    
            boRun_l = false;
        }
        .....
    	QThread::msleep(m_iResponseDelayed);
    
    	QMutexLocker locker(&m_MtxProcess);
    
    	m_WaitCondProcess.wakeOne();
        }
    


  • wofür der frei stehende

    QMutexLocker locker(&m_MtxProcess);
    

    in Zeile 84? Was soll der machen?



  • Ah, dein Erzeuger Prozess wartet auf das Wakeup aus dem erstellten Thread?? Ungewöhnlich und habe ich noch nicht so gesehen. Normalerweise wartet ein Thread darauf, dass er vom Ersteller oder einen anderen Thread abgeholt wird.

    Wie rufst du die Funkionen deines VisaAgilent denn auf?
    Du musst da doch irgendwie sowas haben:

    main(){
    VisaAgilent = agilent(...); // ruft Konstruktor auf und erstellt ersten Thread. Wartet bis der Fertig ist
    agilent.open(); //Open connection-> erstellt auch einen Thread. Wartet auch bis der fertig ist.
    } // Destruktor -> erstellt auch einen Thread, wartet wieder bis der fertig ist.
    

    So hast du nie einen wirklich nebenläufigen Programmablauf (oder habe ich was total übersehen???)

    Deine unterschiede zwischen Debug und Release wird in deinem Fall wahrscheinlich darauf zurückzuführen sein, dass Destruktoren schon mal weg optimiert werden dürfen.



  • Gast3 schrieb:

    wofür der frei stehende

    QMutexLocker locker(&m_MtxProcess);
    

    in Zeile 84? Was soll der machen?

    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.



  • Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    wofür das lock wenn du nichts veränderst?

    oder ist der Code den du zeigst unvollständig?



  • Schlangenmensch schrieb:

    Ah, dein Erzeuger Prozess wartet auf das Wakeup aus dem erstellten Thread?? Ungewöhnlich und habe ich noch nicht so gesehen. Normalerweise wartet ein Thread darauf, dass er vom Ersteller oder einen anderen Thread abgeholt wird.

    Wie rufst du die Funkionen deines VisaAgilent denn auf?
    Du musst da doch irgendwie sowas haben:

    main(){
    VisaAgilent = agilent(...);
    

    // ruft Konstruktor auf und erstellt ersten Thread. Wartet bis der Fertig ist

    agilent.open();}
    

    //Open connection-> erstellt auch einen Thread. Wartet auch bis der fertig ist.
    // Destruktor -> erstellt auch einen Thread, wartet wieder bis der fertig ist.

    Fast
    anbei einen Codeabschnit:

    VisaAgilent DSO_l(.....);/* Object referenzieren*/
    DSO_l.open(); //Bis hier ist alles gut
    // wenn es z.b open verlassen wird also Object "DSO_l" verlassen, wird dann das Destructor aufgerufen und da kracht warum ? --> weiss ich nicht
    

    Schlangenmensch schrieb:

    So hast du nie einen wirklich nebenläufigen Programmablauf (oder habe ich was total übersehen???)

    Deine unterschiede zwischen Debug und Release wird in deinem Fall wahrscheinlich darauf zurückzuführen sein, dass Destruktoren schon mal weg optimiert werden dürfen.



  • Gast3 schrieb:

    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    wofür das lock wenn du nichts veränderst?

    oder ist der Code den du zeigst unvollständig?

    Sorry ich verstee nicht welchen lock meinst du ?



  • Ich sehe grade, dass open auch schon aus dem Konstruktor aufgerufen wird.

    Aber du wirst deinen Code vollständiger posten müssen, aber bitte auf das reduziert, was nötig ist um den Fehler zu reproduzieren.

    Der Destruktor von DSO_l wird aufgerufen, wenn du den Scope verlässt in dem du das erstellt hast. Wobei ich, wie gesagt, davon ausgehe, dass der im Release Modus möglicherweise gar nicht aufgerufen wird.



  • Sorry ich verstee nicht welchen lock meinst du ?

    in deinen Beispiele hier im Forum, Zeile 84



  • Gast3 schrieb:

    Sorry ich verstee nicht welchen lock meinst du ?

    in deinen Beispiele hier im Forum, Zeile 84

    das habe ich doch geantwortet warum:
    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.



  • Schlangenmensch schrieb:

    Ich sehe grade, dass open auch schon aus dem Konstruktor aufgerufen wird.

    Aber du wirst deinen Code vollständiger posten müssen, aber bitte auf das reduziert, was nötig ist um den Fehler zu reproduzieren.

    Der Destruktor von DSO_l wird aufgerufen, wenn du den Scope verlässt in dem du das erstellt hast. Wobei ich, wie gesagt, davon ausgehe, dass der im Release Modus möglicherweise gar nicht aufgerufen wird.

    Ist das Object VisaAgilent DSO_l(....) aufgerufen wird, wird dann der Konstrukt VisaAgilent(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p) aufgerufen.

    Der Konstrukt ist so implementiert:

    VisaAgilent::VisaAgilent(QString strIpAdress_p, int iTimeout_p, bool boSimulate_p, bool boDebug_p)
    {	
    	m_boDebug = boDebug_p;
    	m_boSimulate = boSimulate_p;
    
    	m_enRetVal = enRspOffline;
    	m_strCtrlIP = QString("");
    	m_iTimeout = 0;
    	m_iTimeoutClose = iTimeout_p;
    	if (this->Execute("CreateObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Constructor TcpSocket Create memory error"));
    	}
    
    	this->Open(strIpAdress_p, iTimeout_p);
    }
    

    also folgende verlauf ist vorgesehen:

    1. Objeckt erzeugen:
      diese geschieht wie folgende Implementierung zeigt:
    VisaAgilent::t_enRspType VisaAgilent::Execute(const char *strCmd_p, const int iWaitResponse_p, const int iTimeout_p, const int iRspDelayed_p)
    {
    	VisaAgilent::t_enRspType enRetVal_l = enRspOffline;
    
    	if (!isRunning())
    	{
    		m_ByteArrayRead.clear();
    
    		m_ByteArrayWrite.clear();
    		m_ByteArrayWrite.append(strCmd_p);
    
    		m_iWaitResponse = iWaitResponse_p;
    		m_iTimeout = iTimeout_p;
    		m_iResponseDelayed = iRspDelayed_p;
    
    		start();
    
    		m_MtxProcess.lock();
    		m_WaitCondProcess.wait(&m_MtxProcess,-1);
    		m_MtxProcess.unlock();
    
    		enRetVal_l = this->m_enRetVal;
    	}
    	else
    	{
    		enRetVal_l = enRspError;
    	}
    
    	while(isRunning());
    
    	return enRetVal_l;
    }
    

    In diesen Methode wird run() "Thread" gestartet, die so aussieht:

    void VisaAgilent::run()
    {
    	bool boRun_l = true;
    	bool boSent_l = false;
    
    	const char *pStrCmd_l = NULL;
    	const char *pStrRsp_l = NULL;
    
    	m_enRetVal = enRspError;
    
    	if (strcmp(m_ByteArrayWrite.data(),"CreateObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl = (QTcpSocket *)new QTcpSocket;
    			if (m_pTcpSctCtrl != NULL)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"DeleteObject")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    		}
    		else
    		{
    			if (m_pTcpSctCtrl != NULL)
    			{
    				delete m_pTcpSctCtrl;
    			}
    		}
    
    		m_enRetVal = enRspOK;
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"OpenConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->connectToHost(m_strCtrlIP,5025);
    			if (m_pTcpSctCtrl->waitForConnected(m_iTimeout) == true)
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	if (strcmp(m_ByteArrayWrite.data(),"CloseConnection")==0)
    	{
    		if (this->m_boSimulate == true)
    		{
    			m_enRetVal = enRspOK;
    		}
    		else
    		{
    			m_pTcpSctCtrl->disconnectFromHost();
    			if ((m_pTcpSctCtrl->state() == QAbstractSocket::UnconnectedState) || (m_pTcpSctCtrl->waitForDisconnected(m_iTimeout)))
    			{
    				m_enRetVal = enRspOK;
    			}
    		}
    
    		boRun_l = false;
    	}
    
    	int iTimeout_l = m_iTimeout;
    
    	while (boRun_l && (!this->m_boSimulate))
    	{
     		if (boSent_l == false)
    		{
    			boSent_l = true;
    			// Kommando absetzen
    			m_pTcpSctCtrl->write(m_ByteArrayWrite.data(),m_ByteArrayWrite.size());
    			// Auf Antwort warten
    			if (m_iWaitResponse >= 0)
    			{
    				QThread::msleep(m_iWaitResponse);
    			}
    			else
    			{
    				boRun_l = false;
    			}
    		}
    
    		// Anwort auf Kommando abwarten	
    		if ((m_pTcpSctCtrl->bytesAvailable() > 0) && (boRun_l == true))
    		{
    			m_MtxResponse.lock();
    
    			m_ByteArrayRead.append(m_pTcpSctCtrl->readAll());
    
    			if (m_boDebug)
    			{
    				throw(QString(m_ByteArrayRead.data()));
    			}
    
    			m_MtxResponse.unlock();
    
    			iTimeout_l = m_iTimeout;
    //			iTimeout_l = m_iWaitResponse;
    		}
    		else
    		{
    			if (m_pTcpSctCtrl->waitForReadyRead(iTimeout_l) == false)
    			{
    				m_MtxResponse.lock();
    
    				if (m_ByteArrayRead.size() == 0)
    				{
    					if (m_boDebug)
    					{
    						throw(QString("VisaAgilent Timeout"));
    					}
    					m_enRetVal = enRspTimeout;
    				}
    				else
    				{
    					m_enRetVal = enRspOK;
    				}
    
    				m_MtxResponse.unlock();
    
    				boRun_l = false;					
    			}
    		}
    	}
    
    	QThread::msleep(m_iResponseDelayed);
    
    	QMutexLocker locker(&m_MtxProcess);
    
    	m_WaitCondProcess.wakeOne();
    
    }
    
    1. Verbindung open, die wie folgende geschieht:
    bool VisaAgilent::Open(const QString &strCtrlIP_p, const int iTimeout_p)
    {
    	bool boRet_l = true;
    
    	m_strCtrlIP = strCtrlIP_p;
    
    	if (this->Execute("OpenConnection", 0, iTimeout_p, 0) != enRspOK)
    	{
    		throw(QString("Open TcpSocket Open Connection error"));
    	}
    
    	if (m_boDebug)
    	{
    		throw(QString("Tcp Socket is open"));
    	}
    
    }
    

    die wiederum der Thread aufrufen: seh bitte "run()"

    Wird von dieses Objekt VisaAgilent einen reference erzeugt, so ist immer dieses verlauf vorzugehen.
    Wird dann dieses Object verlassen, muss dann wieder aufgeraumt werden, was eigentlich der Destruktor macht.
    Destruktor Implementierung:

    VisaAgilent::~VisaAgilent()
    {
    	while(isRunning());
    
    	this->Close(m_iTimeoutClose);
    
    	while(isRunning());
    
    	if (this->Execute("DeleteObject", 0, 0, 0) != enRspOK)
    	{
    		throw(QString("Destructor TcpSocket Delete memory error"));
    	}
    
    	while(isRunning());
    }
    

    Das Destruktor ruft wieder der "run()" von Thread um das Object zu löschen
    Ich hoffe es ist jetzt einigemassen klar was das gemacht wird.



  • das habe ich doch geantwortet warum:
    Hier stelle ich sicher, dass der Prozess freigegeben wird, wenn das Object gelöscht wird.

    und wofür ist das lock da wenn du nichts veränderst - einfach mal so oder aus einem Grund? der Code da braucht kein lock



  • Gast3 schrieb:

    und wofür ist das lock da wenn du nichts veränderst - einfach mal so oder aus einem Grund? der Code da braucht kein lock

    Genau habe ich ehrlich gesagt nicht nachgedacht, aber du hast recht.
    Lock brauche ich in diesem Code nicht
    Danke für den Hinweis



  • [quote="Gast3"]

    unter Windows könntest du die Trial-Version vom Intel-Inspector (https://software.intel.com/en-us/intel-inspector-xe) drauflassen

    Ich habe das installiert aber was es gezeigt wird entspricht nicht das Problem, was ich habe.

    Es wird auf andere Qt Library gezeigt, was es wirklich nicht unbedingt das Problem entspricht.

    Ich glaube es ist eine Synchronisation problem.



  • Apropos Synchronisation... Was passiert denn wenn

    m_WaitCondProcess.wakeOne();
    

    aufgerufen wird bevor

    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    

    aufgerufen wurde.



  • Schlangenmensch schrieb:

    Apropos Synchronisation... Was passiert denn wenn

    m_WaitCondProcess.wakeOne();
    

    aufgerufen wird bevor

    m_WaitCondProcess.wait(&m_MtxProcess,-1);
    

    aufgerufen wurde.

    Tread wird nie beendet also SW bleibt hängen


Anmelden zum Antworten